赞
踩
生成token, 就是把 某个东西 以某个key值(密钥) 加密 一下
下面用python举例一下
- # 安装
- pip install pyjwt==1.7.1 (新版本的不行)
-
输入python,在python解析器里,运行生成token(要传payload参数,和key)
- import jwt
-
- paylod={"name":"taoker111"}
-
- token =jwt.encode(payload=paylod,key="tk123")
-
- # 解码 得到payload
- # jwt.decode(token,key="123")
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) 认证功能。
djangorestframework-simplejwt
库(如果尚未安装):
pip install djangorestframework-simplejwt
djangorestframework-simplejwt
默认使用一组默认值,但你可以根据需要设置这些参数。
如:
(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}
djangorestframework-simplejwt
默认使用一组安全的默认值,但你可以根据需要设置这些参数。例如,你可以在 settings.py
中添加以下配置:
- # settings.py
-
- from datetime import timedelta
- SIMPLE_JWT = {
- "AUTH_HEADER_TYPES": ("JWT",), # 指定前缀
- 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60), # 访问令牌过期时间
- 'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1), # 滑动刷新令牌的过期时间
- 'SLIDING_TOKEN_REFRESH_LIFETIME_GRACE_PERIOD': timedelta(minutes=5), # 滑动刷新令牌宽限期
- 'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp', # 滑动刷新令牌的过期时间声明名称
- }
(不改默认的序列化器 和 视图)
自带了 登录视图类 TokenObtainPairView 对应的序列化器TokenObtainSlidingSerializer
(from rest_framework_simplejwt.views import)
(from rest_framework_simplejwt.serializers import)
这么写可以进入到源码
(它的序列化器默认用到的是JWT 里的这个配置 TOKEN_OBTAIN_SERIALIZER,
即rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer)
直接把它配置到urls中,就能使用登录。
在外层urls.py中,配置
- from rest_framework_simplejwt.views import (
- TokenObtainPairView,
- TokenRefreshView,
- TokenVerifyView,
- )
-
- urlpatterns = [
- ...
- path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), # 用于获取
- path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), # 用于更新
- path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'), # 未知
- ...
- ]
获取token
使用POST请求,json格式传递 账号 和密码
即TokenObtainPairSerializer,原有的获取token序列化器要修改下
from rest_framework_simplejwt.serializers import 这么写可以进入到源码)
做法:
在system应用下,或users 应用 中 serializers.py 中
- class LoginSerializer(TokenObtainPairSerializer):
- """
- 用户登录-序列化器(重写的)
- """
- @classmethod
- def get_token(cls, user):
- token = super().get_token(user)
-
- # Add custom claims
- token['name'] = user.username
- # ...
-
- return token
先去完成第二步 (如前面已经配置了url,直接配置 SIMPLE_JWT)
"TOKEN_OBTAIN_SERIALIZER": "system.serializers.LoginSerializer",
登录查看效果,然后使用JWT解析,密钥在setting.py中。
于是access信息(下图的token2)中,就多了name的信息:
如下是重写 获取token的序列化器
- from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
- from django.contrib.auth import authenticate
-
- class LoginSerializer(TokenObtainPairSerializer):
-
- # 可修改一些提示语
- default_error_messages = {
- 'no_active_account': ('该账号已被禁用,请与管理员联系!')
- }
-
- # 响应中,增加了user_info字段, 增加了token字段
- def validate(self, attrs):
- data = super().validate(attrs)
-
- authenticate_kwargs = {
- self.username_field: attrs[self.username_field],
- "password": attrs["password"],
-
- }
-
- self.user = authenticate(**authenticate_kwargs)
-
- user = self.user
- # 获取用户信息
- user_info = {
- 'id': user.id,
- 'username': user.username,
- 'email': user.email,
- # 添加其他用户信息...
- }
-
- # 补充一个token字段
- data["token"] = data["access"]
-
- # 将用户信息添加到响应数据中
- data['user_info'] = user_info
- return data
-
松勤:
是把它当模型序列化器来用,指定了model, fields字段,
并且重写validate,即序列化器里提到的校验方法,并定义响应格式,成功或失败的
- from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
- from django.contrib.auth import authenticate
- from system.models import User
-
-
- class LoginSerializer(TokenObtainPairSerializer):
- class Meta:
- model = User
- fields = "__all__"
- read_only_fields = ["id"]
-
- default_error_messages = {
- 'no_active_account': ('该账号已被禁用,请与管理员联系!')
- }
-
- def validate(self, attrs):
- username = attrs['username']
- password = attrs['password']
- user = User.objects.filter(username=username).first()
- if not user:
- result = {
- "code": 400,
- "msg": "账号或密码不正确!",
- "data": None
- }
- return result
-
- if user and not user.is_staff: # 判断是否允许登录后台
- result = {
- "code": 400,
- "msg": "您没有权限登录后台!",
- "data": None
- }
- return result
-
- if user and not user.is_active:
- result = {
- "code": 400,
- "msg": "该账号已被禁用,请与管理员联系!",
- "data": None
- }
- return result
-
- if user and user.check_password(password): # check_password() 对明文进行加密,并验证
- data = super().validate(attrs)
- refresh = self.get_token(self.user)
-
- data['username'] = self.user.username
- data['userId'] = self.user.id
- data['refresh'] = str(refresh) # refresh_token
- data['access'] = str(refresh.access_token) # access_token
- request = self.context.get('request')
- request.user = self.user
- result = {
- "code": 200,
- "msg": "登录成功!",
- "data": data
- }
- else:
- result = {
- "code": 400,
- "msg": "账号或密码不正确!",
- "data": None
- }
- return result
-
2. 视图类关联新定义的序列化器(假如已经在system应用下,serializers.py文件下重写好了)。
方式1:配置(TokenObtainPairView 视图类自己会找到它)
- SIMPLE_JWT = {
- # It will work instead of the default serializer(TokenObtainPairSerializer).
- "TOKEN_OBTAIN_SERIALIZER": "system.serializers.LoginSerializer", # 应用.模块.类
- # ...
- }
方式2(推荐这个,这样代码可读性高点):views重写登录视图类,并指定自己写的序列化器、 url中改成用新的视图类
- from apps.system.serializers import LoginSerializer
- from rest_framework_simplejwt.views import TokenObtainPairView
- # 2.登录类
- class LoginView(TokenObtainPairView):
- serializer_class = LoginSerializer
url也配置在应用中(有更好的代码可读性)即可
在 Django 的 settings.py
文件中进行设置认证方式中添加:JWTAuthentication:
- # settings.py
-
- REST_FRAMEWORK = {
- # a.在全局指定默认的认证类(指定认证方式)
- 'DEFAULT_AUTHENTICATION_CLASSES': [
- # 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # 先进行token认证(Django 3.1 版本不能用了)
- 'rest_framework_simplejwt.authentication.JWTAuthentication',
- # b.Session会话认证
- 'rest_framework.authentication.SessionAuthentication', # 次要进行session认证
- 'rest_framework.authentication.BasicAuthentication'
- ],
- # 指定使用的权限类
- # a.在全局指定默认的权限类(当认证通过之后,可以获取何种权限)
- 'DEFAULT_PERMISSION_CLASSES': [
- # AllowAny 不管是否有认证成功,都能获取所有权限
- # IsAdminUser 管理员(管理员需要登录)具备所有权限
- # IsAuthenticated 只要登录,就具备所有权限
- # IsAuthenticatedOrReadOnly,如果登录了就具备所有权限,不登录只具备读取数据的权限
- 'rest_framework.permissions.AllowAny',
- ],
- # 其他设置...
- }
假如不登录
登录,获取到token
其他接口中请求头中,传递Authorization,值默认为Bearer +空格 + 登录返回的access值
官方文档地址是:Simple JWT — Simple JWT 5.2.2.post27+g47b7a08 documentation
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。