原文链接:https://blog.csdn.net/weixin_45912307/article/details/110456550
1. 后端接口分析–登录功能
1.1 请求方式: post
1.2 请求路径:django_admin/authorization
1.3 请求参数:
{
"usernname":"jsonLiu",
"user_id":8100,
"token":"afagagaf856123054AFAGHAHGV"
}
1.4 响应结果
2. Json web token (JWT)业务逻辑
2.1 用户使用用户名密码来请求服务器
2.2 服务器进行验证用户的信息
2.3 服务器通过验证发送给用户一个token
2.4 客户端存储token,并在每次请求时附送上这个token值
2.5 服务端验证token值,并返回数据
3. 后端逻辑实现
3.1 安装配置
ppip install djangorestframework-jwt
3.2 在settings.py文件中添加如下配置
import datetime
REST_FRAMEWORK = {
# 指定认证
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
# jwt配置
JWT_AUTH = {
# 指定有效期
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
# 指定返回结果方法
'JWT_RESPONSE_PAYLOAD_HANDLER':
'django_admin.utils.jwt_response_payload_handler',
}
3.3 在登录子应用django_admind的urls.py中添加路由信息
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
url(r'^authorizations/$', obtain_jwt_token),
]
3.4 将子应用添加到项目路由urls.py文件中
from django.conf.urls import url
from django.urls import include
urlpatterns = [
url(r'^django_admin/',include('django_admin.urls'))
]
3.5 在子应用下新建utils.py文件, 重写jwt_response_payload_handler方法(原生方法只返回token,不符合需求)
def jwt_response_payload_handler(token, user=None, request=None):
"""
自定义jwt认证成功返回数据
"""
return {
'token': token,
'id': user.id,
'username': user.username
}
3.6 在django_admin/utils/authenticate.py中重写authenticate的方法(让管理员用户才能登录admin后台)
from django.contrib.auth.backends import ModelBackend
from users.models import User
class djangoModelBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
if request is None:
# 后台登录
try:
# is_superuser判断是否是超级管理员用户
user = User.objects.get(username=username, superuser=True)
except:
user = None
# 判断密码
if user is not None and user.check_password(password):
return user
else:
# 前台登录
# 变量username的值,可以是用户名,也可以是手机号,需要判断,再查询
try:
# if re.match(r'^1[3-9]\d{9}$', username):
# user = User.objects.get(mobile=username)
# else:
# user = User.objects.get(username=username)
user = User.objects.get(username=username)
except:
# 如果未查到数据,则返回None,用于后续判断
try:
user = User.objects.get(mobile=username)
except:
return None
# return None
# 判断密码
if user.check_password(password):
return user
else:
return None
4. jwt原理及构成
4.1 session认证机制
4.2 token认证机制流程形式
4.3 jwt组成
- (header)头部承载两部分信息:
base64
- 声明token类型,这里是jwt
- 声明加密的算法 通常直接使用 HMAC SHA256
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
- payload(载荷)就是存放有效信息的地方
base64
- iss: jwt签发者
- exp: jwt的过期时间
- iat: jwt的签发时间
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
- signature(签证信息)
sha256
- header (base64后的)
- payload (base64后的)
- secret
base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加secret组合加密,然后就构成了jwt的第三部分
// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload)
var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
- signature(签名)
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
- jwt最终组成(将header、payload、signature用. 进行连接)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
4.4 jwt工作总流程