当前位置:   article > 正文

四、【Django】基于Jwt的token认证(登录接口)_django jwt

django jwt

简介

生成token, 就是把  某个东西  以某个key值(密钥)  加密 一下

简单的生成token举例

下面用python举例一下

  1. # 安装
  2. pip install pyjwt==1.7.1 (新版本的不行)

输入python,在python解析器里,运行生成token(要传payload参数,和key)

  1. import jwt
  2. paylod={"name":"taoker111"}
  3. token =jwt.encode(payload=paylod,key="tk123")
  4. # 解码 得到payload
  5. # jwt.decode(token,key="123")

Django_rf的simplejwt

Django 3.1 版本之前是使用rest_framework_jwt 库,   之后版本的django会遇到这个报错

Could not import 'rest_framework_jwt.authentication.JSONWebTokenAuthentication' for API setting 'DEFAULT_AUTHENTICATION_CLASSES'. ImportError: cannot import name 'smart_text' from 'django.utils.encoding'

djangorestframework-simplejwt 库提供了与 rest_framework_jwt 类似的 JSON Web Token (JWT) 认证功能。

1.安装

djangorestframework-simplejwt 库(如果尚未安装):

pip install djangorestframework-simplejwt

2.JWT 库默认的参数

 djangorestframework-simplejwt 默认使用一组默认值,但你可以根据需要设置这些参数。

如:

  •   默认token有效期为 5分钟
  •   生成token密钥SIGNING_KEY默认为 :setting.py 中, 创建项目就生成好了的一个 key值
  •  参数:AUTH_HEADER_TYPES 指定前缀,默认为Bearer

(from rest_framework_simplejwt.settings import )这么写然后点击settings

 如下是AUTH_HEADER_TYPES 前缀的意思,如果不配置,就是 Bearer开头

(后续可以登录成功后的access)使用pyjwt库来,用你的key来解码试试,它的信息包含这些

{'token_type': 'access', 'exp': 1689661573, 'iat': 1689661513, 'jti': 'eedea8e9d74b4da8b9e1932624952ee8', 'user_id': 3}

自定义配置JWT

 djangorestframework-simplejwt 默认使用一组安全的默认值,但你可以根据需要设置这些参数。例如,你可以在 settings.py 中添加以下配置:

  1. # settings.py
  2. from datetime import timedelta
  3. SIMPLE_JWT = {
  4. "AUTH_HEADER_TYPES": ("JWT",), # 指定前缀
  5. 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60), # 访问令牌过期时间
  6. 'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1), # 滑动刷新令牌的过期时间
  7. 'SLIDING_TOKEN_REFRESH_LIFETIME_GRACE_PERIOD': timedelta(minutes=5), # 滑动刷新令牌宽限期
  8. 'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp', # 滑动刷新令牌的过期时间声明名称
  9. }

直接使用写登录

(不改默认的序列化器 和 视图)

自带了 登录视图类 TokenObtainPairView  对应的序列化器TokenObtainSlidingSerializer

(from rest_framework_simplejwt.views import)
(from rest_framework_simplejwt.serializers import)
这么写可以进入到源码

(它的序列化器默认用到的是JWT 里的这个配置 TOKEN_OBTAIN_SERIALIZER, 

 即rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer)

利用本身的TokenObtainPairView  和 TokenObtainSlidingSerializer实现登录

直接把它配置到urls中,就能使用登录

在外层urls.py中,配置

  1. from rest_framework_simplejwt.views import (
  2. TokenObtainPairView,
  3. TokenRefreshView,
  4. TokenVerifyView,
  5. )
  6. urlpatterns = [
  7. ...
  8. path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), # 用于获取
  9. path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), # 用于更新
  10. path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'), # 未知
  11. ...
  12. ]

获取token

使用POST请求,json格式传递 账号 和密码

自定义登录接口:

第一步:重写序列化器

即TokenObtainPairSerializer,原有的获取token序列化器要修改下

 from rest_framework_simplejwt.serializers import    这么写可以进入到源码)

token值中增加其他信息(不常用)

 做法:

在system应用下,或users 应用 中  serializers.py 中

  1. class LoginSerializer(TokenObtainPairSerializer):
  2. """
  3. 用户登录-序列化器(重写的)
  4. """
  5. @classmethod
  6. def get_token(cls, user):
  7. token = super().get_token(user)
  8. # Add custom claims
  9. token['name'] = user.username
  10. # ...
  11. return token

先去完成第二步 (如前面已经配置了url,直接配置 SIMPLE_JWT)

"TOKEN_OBTAIN_SERIALIZER": "system.serializers.LoginSerializer",

登录查看效果,然后使用JWT解析,密钥在setting.py中。

于是access信息(下图的token2)中,就多了name的信息:

修改响应结构、补充字段等

  • 序列化器:里面增加了user_info  用户信息( 这里的话,要配置setting,才生效)

如下是重写  获取token的序列化器 

  1. from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
  2. from django.contrib.auth import authenticate
  3. class LoginSerializer(TokenObtainPairSerializer):
  4. # 可修改一些提示语
  5. default_error_messages = {
  6. 'no_active_account': ('该账号已被禁用,请与管理员联系!')
  7. }
  8. # 响应中,增加了user_info字段, 增加了token字段
  9. def validate(self, attrs):
  10. data = super().validate(attrs)
  11. authenticate_kwargs = {
  12. self.username_field: attrs[self.username_field],
  13. "password": attrs["password"],
  14. }
  15. self.user = authenticate(**authenticate_kwargs)
  16. user = self.user
  17. # 获取用户信息
  18. user_info = {
  19. 'id': user.id,
  20. 'username': user.username,
  21. 'email': user.email,
  22. # 添加其他用户信息...
  23. }
  24. # 补充一个token字段
  25. data["token"] = data["access"]
  26. # 将用户信息添加到响应数据中
  27. data['user_info'] = user_info
  28. return data

 松勤:

是把它当模型序列化器来用,指定了model, fields字段,

并且重写validate,即序列化器里提到的校验方法,并定义响应格式,成功或失败的

  1. from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
  2. from django.contrib.auth import authenticate
  3. from system.models import User
  4. class LoginSerializer(TokenObtainPairSerializer):
  5. class Meta:
  6. model = User
  7. fields = "__all__"
  8. read_only_fields = ["id"]
  9. default_error_messages = {
  10. 'no_active_account': ('该账号已被禁用,请与管理员联系!')
  11. }
  12. def validate(self, attrs):
  13. username = attrs['username']
  14. password = attrs['password']
  15. user = User.objects.filter(username=username).first()
  16. if not user:
  17. result = {
  18. "code": 400,
  19. "msg": "账号或密码不正确!",
  20. "data": None
  21. }
  22. return result
  23. if user and not user.is_staff: # 判断是否允许登录后台
  24. result = {
  25. "code": 400,
  26. "msg": "您没有权限登录后台!",
  27. "data": None
  28. }
  29. return result
  30. if user and not user.is_active:
  31. result = {
  32. "code": 400,
  33. "msg": "该账号已被禁用,请与管理员联系!",
  34. "data": None
  35. }
  36. return result
  37. if user and user.check_password(password): # check_password() 对明文进行加密,并验证
  38. data = super().validate(attrs)
  39. refresh = self.get_token(self.user)
  40. data['username'] = self.user.username
  41. data['userId'] = self.user.id
  42. data['refresh'] = str(refresh) # refresh_token
  43. data['access'] = str(refresh.access_token) # access_token
  44. request = self.context.get('request')
  45. request.user = self.user
  46. result = {
  47. "code": 200,
  48. "msg": "登录成功!",
  49. "data": data
  50. }
  51. else:
  52. result = {
  53. "code": 400,
  54. "msg": "账号或密码不正确!",
  55. "data": None
  56. }
  57. return result

 第二步:把重写的序列化器配置起来。

2. 视图类关联新定义的序列化器(假如已经在system应用下,serializers.py文件下重写好了)。

        方式1:配置(TokenObtainPairView 视图类自己会找到它)

  1. SIMPLE_JWT = {
  2. # It will work instead of the default serializer(TokenObtainPairSerializer).
  3. "TOKEN_OBTAIN_SERIALIZER": "system.serializers.LoginSerializer", # 应用.模块.类
  4. # ...
  5. }
   方式2(推荐这个,这样代码可读性高点):views重写登录视图类,并指定自己写的序列化器、  url中改成用新的视图类
  1. from apps.system.serializers import LoginSerializer
  2. from rest_framework_simplejwt.views import TokenObtainPairView
  3. # 2.登录类
  4. class LoginView(TokenObtainPairView):
  5. serializer_class = LoginSerializer

 url也配置在应用中(有更好的代码可读性)即可

认证方式设置为jwttoken认证

在 Django 的 settings.py 文件中进行设置认证方式中添加:JWTAuthentication:

  1. # settings.py
  2. REST_FRAMEWORK = {
  3. # a.在全局指定默认的认证类(指定认证方式)
  4. 'DEFAULT_AUTHENTICATION_CLASSES': [
  5. # 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # 先进行token认证(Django 3.1 版本不能用了)
  6. 'rest_framework_simplejwt.authentication.JWTAuthentication',
  7. # b.Session会话认证
  8. 'rest_framework.authentication.SessionAuthentication', # 次要进行session认证
  9. 'rest_framework.authentication.BasicAuthentication'
  10. ],
  11. # 指定使用的权限类
  12. # a.在全局指定默认的权限类(当认证通过之后,可以获取何种权限)
  13. 'DEFAULT_PERMISSION_CLASSES': [
  14. # AllowAny 不管是否有认证成功,都能获取所有权限
  15. # IsAdminUser 管理员(管理员需要登录)具备所有权限
  16. # IsAuthenticated 只要登录,就具备所有权限
  17. # IsAuthenticatedOrReadOnly,如果登录了就具备所有权限,不登录只具备读取数据的权限
  18. 'rest_framework.permissions.AllowAny',
  19. ],
  20. # 其他设置...
  21. }

假如不登录

 登录,获取到token

 

 其他接口中请求头中,传递Authorization,值默认为Bearer  +空格 +   登录返回的access值

官方文档地址是:Simple JWT — Simple JWT 5.2.2.post27+g47b7a08 documentation

  1. 安装和配置
  2. JWT 认证的使用方法和示例
  3. 设置 JWT 认证的参数和选项
  4. 刷新令牌和滑动刷新令牌的使用
  5. 撤销令牌的使用方法
  6. JWT 认证视图
  7. 自定义认证逻辑
  8. 常见问题解答
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/638521
推荐阅读
相关标签
  

闽ICP备14008679号