简介

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

简单的生成token举例

下面用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_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 中添加以下配置:

# 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)

利用本身的TokenObtainPairView  和 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    这么写可以进入到源码)

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

 做法:

在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的信息:

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

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

如下是重写  获取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也配置在应用中(有更好的代码可读性)即可

认证方式设置为jwttoken认证

在 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

安装和配置JWT 认证的使用方法和示例设置 JWT 认证的参数和选项刷新令牌和滑动刷新令牌的使用撤销令牌的使用方法JWT 认证视图自定义认证逻辑常见问题解答

好文链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: