djangorestframework-simplejwt高级定制(有效荷载与响应数据结构)教程

╰半橙微兮° 2022-10-07 09:53 429阅读 0赞

djangorestframework-simplejwt高级定制教程

文章目录

  • djangorestframework-simplejwt高级定制教程
    • 定制响应数据格式与内容
      • 1.编写自定义的序列化类
        1. 在视图中使用自定义的序列化类
    • 后台获取payload中的数据
    • Web端解析Token获取数据
        1. js代码直接解析
        1. npm安装`jsonwebtoken`模块解析
    • 演示下载

本文为djangorestframework-simplejwt入门教程的高级篇,上一篇里面讲述了simplejwt的基本使用,包括安装,添加到项目,验证等。本文将接着上一页的内容继续,不再讲解安装配置等内容。如果没有特殊的需求的话,上一章的内容以及足够完成jwt验证了,但是在实际企业里面,总会有一些定制的需求,因此,本文主要简单介绍如何定制响应数据。

定制响应数据格式与内容

对于获取Token的接口,simplejwt默认返回的数据仅有accessrefresh两个信息,对于常规的网站来说,有这两个信息已经足够了,通过解析token就可以得到很多信息。但是总会有那么一些时候,需要在响应的数据里面添加字段,比如系统以前是直接将用户信息直接放在响应数据里面的,出于兼容性考虑,响应数据还需要添加一些数据,因此,我们需要定制登录接口。

1.编写自定义的序列化类

要想自定义响应数据,就需要修改默认的序列化类TokenObtainPairSerializer。编写一个自定义的序列化类,继承自TokenObtainPairSerializer,然后重写它的两个方法:

  • get_token: 生成Token的方法,重写这个方法修改有效荷载payload
  • validate:重写这个方法修改响应数据结构

完整代码如下(serializers.py

  1. from django.contrib.auth import get_user_model
  2. from rest_framework import serializers
  3. from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
  4. # 如果自定义了用户表,那么就要使用这个方法来获取用户模型
  5. # 没有自定义的话可以使用以下方式加载用户模型:
  6. # from django.contrib.auth.models import User
  7. # 不过这种是万能的
  8. User = get_user_model()
  9. # 重写TokenObtainPairSerializer类的部分方法以实现自定义数据响应结构和payload内容
  10. class MyTokenSerializer(TokenObtainPairSerializer):
  11. @classmethod
  12. def get_token(cls, user):
  13. """
  14. 此方法往token的有效负载 payload 里面添加数据
  15. 例如自定义了用户表结构,可以在这里面添加用户邮箱,头像图片地址,性别,年龄等可以公开的信息
  16. 这部分放在token里面是可以被解析的,所以不要放比较私密的信息
  17. :param user: 用戶信息
  18. :return: token
  19. """
  20. token = super().get_token(user)
  21. # 添加个人信息
  22. token['name'] = user.username
  23. return token
  24. def validate(self, attrs):
  25. """
  26. 此方法为响应数据结构处理
  27. 原有的响应数据结构无法满足需求,在这里重写结构如下:
  28. {
  29. "refresh": "xxxx.xxxxx.xxxxx",
  30. "access": "xxxx.xxxx.xxxx",
  31. "expire": Token有效期截止时间,
  32. "username": "用户名",
  33. "email": "邮箱"
  34. }
  35. :param attrs: 請求參數
  36. :return: 响应数据
  37. """
  38. # data是个字典
  39. # 其结构为:{'refresh': '用于刷新token的令牌', 'access': '用于身份验证的Token值'}
  40. data = super().validate(attrs)
  41. # 获取Token对象
  42. refresh = self.get_token(self.user)
  43. # 令牌到期时间
  44. data['expire'] = refresh.access_token.payload['exp'] # 有效期
  45. # 用户名
  46. data['username'] = self.user.username
  47. # 邮箱
  48. data['email'] = self.user.email
  49. return data

2. 在视图中使用自定义的序列化类

views.py中编写新的视图实现登陆功能

  1. from rest_framework import status
  2. from rest_framework.response import Response
  3. from rest_framework_simplejwt.views import TokenViewBase
  4. from .serializers import MyTokenSerializer
  5. # 自定义的登陆视图
  6. class LoginView(TokenViewBase):
  7. serializer_class = MyTokenSerializer # 使用刚刚编写的序列化类
  8. # post方法对应post请求,登陆时post请求在这里处理
  9. def post(self, request, *args, **kwargs):
  10. # 使用刚刚编写时序列化处理登陆验证及数据响应
  11. serializer = self.get_serializer(data=request.data)
  12. try:
  13. serializer.is_valid(raise_exception=True)
  14. except Exception as e:
  15. raise ValueError(f'验证失败: {
  16. e}')
  17. return Response(serializer.validated_data, status=status.HTTP_200_OK)

最后记得要配置一下url.py

  1. from django.urls import path
  2. from .views import LoginView, DemoView
  3. app_name = 'account'
  4. urlpatterns = [
  5. path('login/', LoginView.as_view()), # 使用自定义的视图进行登录
  6. ]

后台获取payload中的数据

在生成token的时候,我们往里面添加了一些数据,那么这些数据是可以拿出来用的

编写用于测试的视图,

  1. # 用于演示后台获取token中payload数据的视图
  2. class DemoView(APIView):
  3. def get(self, request):
  4. # 通过request.auth获取用户Token
  5. print('请求用户Token为:')
  6. print(request.auth)
  7. # 通过request.auth.payload可以获取到解析后的payload内容(字典类型)
  8. print("\n有效荷载信息:")
  9. print(request.auth.payload)
  10. return HttpResponse('身份验证通过!', status=status.HTTP_200_OK)

然后配置一下url进行测试,得到一下运行结果

  1. 请求用户Token为:
  2. eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjIzOTA2MTk1LCJqdGkiOiJmY2FjNjhhMzk3M2U0Y2Q0OTJkZjQ0YTFlNzc2ODA4MiIsInVzZXJfaWQiOjEsIm5hbWUiOiJhZG1pbiJ9.9Xd7oHIyMPFR1ZwR3RS0Kzwb2TUO_fVHB5ZFTmjtgrY
  3. 有效荷载信息:
  4. {'token_type': 'access', 'exp': 1623906195, 'jti': 'fcac68a3973e4cd492df44a1e7768082', 'user_id': 1, 'name': 'admin'}

Web端解析Token获取数据

1. js代码直接解析

  1. let token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjIyNzEwNTkzLCJqdGkiOiIwYjg0ZjYzODkyNWY0YjE5Yjc1MzE4Njc4YmFhYTU5YiIsInVzZXJfaWQiOjEsIm5hbWUiOiJhZG1pbiJ9.-oSnx9ex__ZDi8-fOAV3tO-yFdCRhufxgEEkCQw8_9M';
  2. // 解析token, 分割token,取出第二段(payload)进行解析
  3. let user = JSON.parse(decodeURIComponent(escape(window.atob(token.split('.')[1]))))
  4. console.log("user", user)

效果如下:

e2ff852447ef56584d3fdb072641b687.png

2. npm安装jsonwebtoken模块解析

如果项目中使用了npm,那么可以利用npm快速安装一个模块来解析Token

  1. 安装模块: npm install jsonwebtoken
  2. 在js文件中使用jsonwebtoken

    // 引入模块
    var jwt = require(‘jsonwebtoken’);
    // 要解析的token
    let tokenString = ‘eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjIyNzEwNTkzLCJqdGkiOiIwYjg0ZjYzODkyNWY0YjE5Yjc1MzE4Njc4YmFhYTU5YiIsInVzZXJfaWQiOjEsIm5hbWUiOiJhZG1pbiJ9.-oSnx9ex__ZDi8-fOAV3tO-yFdCRhufxgEEkCQw8_9M’
    // 使用decode方法解析token
    let token = jwt.decode(tokenString)
    console.log(token)

最终的效果如下:

e26de874ad774ce804d5006807b8882d.png

演示下载

演示代码已上传至github:

https://github.com/WuChengqian520/djangorestframework-simplejwt-demo.git

基础用法位于master分支

定制Token位于advanced分支

发表评论

表情:
评论列表 (有 0 条评论,429人围观)

还没有评论,来说两句吧...

相关阅读

    相关 数据结构算法】高级排序

    希尔排序是插入排序的一种,又称为 “缩小增量排序”,是插入排序算法的一种更高效的改进版本。在使用插入排序的时候,我们会发现一个很不友好的情况,如果已经排序的分组元素为 {...