drf学习笔记
今日内容概要
- simpleui集成监控大屏
- 双token认证
- restframework-jwt执行流程分析
今日内容详细
simpleui集成监控大屏
# 从gitee上找到开源的前端页面---》集成到项目中即可
gitee网址:https://gitee.com/lvyeyou/DaShuJuZhiDaPingZhanShi?_from=gitee_search
# 本质就是前后端混合的项目
双token认证
# 签发的token,有过期时间,一般是300秒。可以在配置文件中添加下面配置自定义过期时间,配置一般设为7天
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
}
用户正在app或者应用中操作,token突然过期,此时用户不得不返回登录界面,重新进行一次登录,这种体验性不好,于是引入双token校验机制。
使用:
首次登陆时服务端返回两个token ,accessToken和refreshToken,accessToken过期时间比较短,refreshToken时间较长,且每次使用后会刷新,每次刷新后的refreshToken都是不同。
优势:
accessToken的存在,保证了登录态的正常验证,因其过期时间的短暂也保证了帐号的安全性。
refreshToekn的存在,保证了用户无需在短时间内进行反复的登陆操作来保证登录态的有效性,同时也保证了活跃用户的登录态可以一直存续而不需要进行重新登录,反复刷新也防止某些不怀好意的人获取refreshToken后对用户帐号进行动手动脚的操作。
流程:
登录操作,在后台服务器验证账号密码成功之后返回2个token:accessToken和refreshToken。
在进行服务器请求的时候,先将Token发送验证,如果accessToken有效,则正常返回请求结果;如果accessToken无效,则验证refreshToken。
此时如果refreshToken有效则返回请求结果和新的accessToken和新的refreshToken。如果refreshToken无效,则提示用户进行重新登陆操作。
例子:
refreshToken假设7天,accessToken过期时间5分钟。
正常使用accessToken即可,如果accessToken过期了,重新发请求,携带refreshToken过来,能正常返回响应,并且这次响应中又带了acessToken。
注意:django中顶格写的代码,都会执行。
restframework-jwt执行流程分析
# 签发流程--》本质就是登录接口---》【校验用户是否正确,如果正确签发token】写到了序列化类中,如果不正确返回错误
1. 入口:path('login/', obtain_jwt_token)
obtain_jwt_token:核心代码--ObtainJSONWebToken.as_view()
ObtainJSONWebToken 视图类,实现了登录功能
class ObtainJSONWebToken(JSONWebTokenAPIView):
serializer_class = JSONWebTokenSerializer
2.来到父类:JSONWebTokenAPIView
class JSONWebTokenAPIView(APIView):
# 局部禁用掉权限和认证
permission_classes = ()
authentication_classes = ()
def get_serializer_context(self):
return {
'request': self.request,
'view': self,
}
def get_serializer_class(self):
return self.serializer_class
def get_serializer(self, *args, **kwargs):
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
def post(self, request, *args, **kwargs):
# JSONWebTokenSerializer实例化得到一个序列化类的对象,传入前端传的值
serializer = self.get_serializer(data=request.data)
if serializer.is_valid(): # 校验前端传入的数据是否合法:
#1 字段自己的规则 2 局部钩子 3 全局钩子(序列化类的validate方法)
# 获取当前登录用户和签发token是在序列化类中完成的
# 从序列化类对象中取出了当前登录用户
user = serializer.object.get('user') or request.user
# # 从序列化类对象中取出了token
token = serializer.object.get('token')
# 自定义过返回什么格式,前端看到的就是什么样子
response_data = jwt_response_payload_handler(token, user, request)
response = Response(response_data)
return response
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
3.来到序列化类:JSONWebTokenSerializer
class JSONWebTokenSerializer(Serializer):
def validate(self, attrs):
credentials = {
# 'username': attrs.get('username')
self.username_field: attrs.get(self.username_field),
# 'password': attrs.get('password')
'password': attrs.get('password')
}
if all(credentials.values()):
# auth模块的校验用户名和密码是否正确
user = authenticate(**credentials)
if user:
if not user.is_active:
msg = _('User account is disabled.')
raise serializers.ValidationError(msg)
# # 通过用户获得payload:{}
payload = jwt_payload_handler(user)
return {
'token': jwt_encode_handler(payload),
'user': user
}
else:
msg = _('Unable to log in with provided credentials.')
# 根据用户名和密码查不到用户
raise serializers.ValidationError(msg)
else:
msg = _('Must include "{username_field}" and "password".')
msg = msg.format(username_field=self.username_field)
# # 用户名和密码不传,传多了都不行
raise serializers.ValidationError(msg)
# 认证流程
1.入口:from rest_framework_jwt.authentication import JSONWebTokenAuthentication
JSONWebTokenAuthentication认证类
class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication):
www_authenticate_realm = 'api'
def get_jwt_value(self, request):
# get_authorization_header(request)根据请求头中HTTP_AUTHORIZATION,取出token
# token格式是:jwt adsfasdfasdfad
# auth=['jwt','真正的token']
auth = get_authorization_header(request).split()
auth_header_prefix = api_settings.JWT_AUTH_HEADER_PREFIX.lower()
if not auth:
if api_settings.JWT_AUTH_COOKIE:
return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
return None
if smart_text(auth[0].lower()) != auth_header_prefix:
return None
if len(auth) == 1:
msg = _('Invalid Authorization header. No credentials provided.')
raise exceptions.AuthenticationFailed(msg)
elif len(auth) > 2:
msg = _('Invalid Authorization header. Credentials string '
'should not contain spaces.')
raise exceptions.AuthenticationFailed(msg)
return auth[1]
def authenticate_header(self, request):
return '{0} realm="{1}"'.format(api_settings.JWT_AUTH_HEADER_PREFIX, self.www_authenticate_realm)
2.来到父类:BaseJSONWebTokenAuthentication中找authenticate方法
class BaseJSONWebTokenAuthentication(BaseAuthentication):
def authenticate(self, request):
# jwt_value前端传入的token
jwt_value = self.get_jwt_value(request)
# 前端没有传入token,return None,没有带token,认证类也能过,所有咱们才加权限类
if jwt_value is None:
return None
try:
# 验证token,token合法,返回payload
payload = jwt_decode_handler(jwt_value)
except jwt.ExpiredSignature:
msg = _('Signature has expired.')
raise exceptions.AuthenticationFailed(msg)
except jwt.DecodeError:
msg = _('Error decoding signature.')
raise exceptions.AuthenticationFailed(msg)
except jwt.InvalidTokenError:
raise exceptions.AuthenticationFailed()
# 通过payload得到当前登录用户
user = self.authenticate_credentials(payload)
# 后期的request.user就是当前登录用户
return (user, jwt_value)
# 它这个认证类:只要带了token,request.user就有值,如果没带token,不管了,继续往后走,所以才要加权限类
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了