Django上课笔记(八)——整合JWT实现前后端分离
Django上课笔记(八)——整合JWT实现前后端分离
1.下载相关的包
pip install djangorestframework
pip install pyjwt
pip install djangorestframework-simplejwt
2.将可视化的JWT项目注册进app中
2.1
在
acapp/settings.py中,修改INSTALLED_APPS课上代码链接:<https://git.acwing.com/yxc/acapp/-/blob/rest_and_jwt/acapp/settings.py>
2.2
在
acapp/settings.py中增加REST_FRAMEWORK相关配置:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}2.3
在
acapp/settings.py中增加JWT相关配置:
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=14),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': False,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': "JdsfjdsfkjSDfhsdf89123SFDf",
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'JWK_URL': None,
'LEEWAY': 0,
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}注意其中的'SIGNING_KEY' 可以设置为你想设置的随机字符串
2.4
在
acapp/settings.py中增加需要用到的包timedelta
3.修改登陆业务
3.1
在
game/urls/settings/index.py中引入JWT相关界面及其地址代码链接:<https://git.acwing.com/zengxing358/acapp/-/blob/master/game/urls/settings/index.py>
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
#参数分别为:地址栏中的路径名;函数名;自己起的名字
path("token/", TokenObtainPairView.as_view(), name="settings_token"),
path("token/refresh/", TokenRefreshView.as_view(), name="settings_token_refresh"),
..........
]3.2
将
rest_framework app中的前端代码同步到项目在acapp主目录中执行:
python3 manage.py collectstatic登陆业务的重要说明
由于引入的rest_framework_simplejwt,已经帮我们实现了登陆业务的逻辑,所以,原来的game/views/settings/login.py和game/views/settings/logout.py可以删除
4.重写JWT版的单点登陆
4.1
重写
game/views/settings/getinfo.py中的业务逻辑
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from game.models.player.player import Player
class InfoView(APIView):
permission_classes = ([IsAuthenticated])
def get(self, request):
user = request.user
player = Player.objects.get(user=user)
return Response({
'result': "success",
'username': user.username,
'photo': player.photo,
})同时还得在
game/urls/settings/index.py中将修改后的函数名导入更换
from django.urls import path,include
from game.views.settings.getinfo import InfoView
from game.views.settings.register import register
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
#参数分别为:地址栏中的路径名;函数名;自己起的名字
path("token/", TokenObtainPairView.as_view(), name="settings_token"),
path("token/refresh/", TokenRefreshView.as_view(), name="settings_token_refresh"),
path("getinfo/", InfoView.as_view(), name="settings_getinfo"),
path("register/", register, name="settings_register"),
path("acwing_info/",include("game.urls.settings.acwing_info.index")),
path("gitee_info/",include("game.urls.settings.gitee_info.index")),
path("github_info/",include("game.urls.settings.github_info.index")),
]5.修改前端
5.1
在
game/static/js/src/zbase.js中,添加2个新参数
constructor(id,AcWingOS,access,refrash){
this.access = access
this.refash = refrash
}并在
game/templates/multiends/web.html中加入这两个参数
let ac_game = new AcGame("ac_game_12345678",null,"","");5.2
在
game/static/js/src/settings/zbase.js中,修改前端登陆逻辑
注意以下改动
修改登陆功能
5.2.1
/**
* 在对象创建时执行的函数
*/
start() {
if (this.platform === "ACAPP") {
this.getinfo_acapp();
} else {
if (this.root.access) {
this.getinfo_web();
}else{
this.open_login_view();
}
this.add_listening_events();
}
}5.2.2
/**
* 向后端发送填写的账号密码,验证并返回信息
*/
login_on_remote() { // 在远程服务器上登录
let username = this.$login_username.val();
let password = this.$login_password.val();
this.$login_error_message.empty();
$.ajax({
url: "https://game.liuyutao666.top/settings/token/",
type: "post",
data: {
username: username,
password: password,
},
success: (resp)
=> {
console.log(resp);
this.root.access = resp.access;
this.root.refresh = resp.refresh;
this.refresh_jwt_token();
this.getinfo_web();
},
error: () => {
this.$login_error_message.html("用户名或密码错误");
}
})
;
}5.2.3
getinfo_web() {
$.ajax({
url: "https://game.liuyutao666.top/settings/getinfo/",
type: "GET",
data: {
platform: outer.platform,
},
headers: {
//这里的Bearer是settings中,SIMPLE_JWT,中定义的'AUTH_HEADER_TYPES': ('Bearer',),
//注意这里Bearer后必须有空格
'Authorization': "Bearer " + this.root.access,
},
//得到后端参数后执行的函数
success: resp =>{
if (resp.result === "success") {
this.username = resp.username;
this.photo = resp.photo;
//登录界面隐藏
this.hide();
//显示菜单界面
this.root.menu.show();
} else {
//获取信息失败(即用户未登录),则继续显示登录界面
this.open_login_view();
}
}
});
}5.2.4
修改退出功能
logout_on_remote() {
if (this.platform === "ACAPP") {
this.root.AcWingOS.api.window.close();
}else{
this.root.access = "";
this.root.refresh = "";
location.href = "/"
}6.修改一键登陆的逻辑
6.1
修改web登陆逻辑,在
game/views/settings/acwing_info/web/receive_code.py
#from django.shortcuts import redirect
from django.shortcuts import redirect,reverse
from django.core.cache import cache
import requests
from django.contrib.auth.models import User
from game.models.player.player import Player
#from django.contrib.auth import login
from rest_framework_simplejwt.tokens import RefreshToken
from random import randint
def receive_code(request):
openid = access_token_res['openid']
players = Player.objects.filter(openid=openid)
# if players.exists():
# login(request, players[0].user)
# return redirect("index")
if players.exists():
refresh = RefreshToken.for_user(players[0].user)
return redirect(reverse("index") + "?access=%s&refresh=%s" % (str(refresh.access_token), str(refresh)))
get_userinfo_url = "https://www.acwing.com/third_party/api/meta/identity/getinfo/"
params = {
user = User.objects.create(username=username)
player = Player.objects.create(user=user, photo=photo, openid=openid)
#login(request, user)
refresh = RefreshToken.for_user(user)
return redirect(reverse("index") + "?access=%s&refresh=%s" % (str(refresh.access_token), str(refresh)))
#return redirect("index")6.2
修改
game/views/index.py
from django.shortcuts import render
def index(request):
data = request.GET
context = {
'access': data.get('access', ""),
'refresh': data.get('refresh', ""),
}
return render(request, "multiends/web.html", context)7.实现token刷新逻辑
7.1
在前端实现刷新逻辑