0. 介绍
因为jwt官方已经停止维护,且对于django4.x不支持,所以选择simplejwt(django>=2.0)
一定要配合权限一起使用,不然不生效
1.使用
1.1 安装
先安装drf,因为jwt仅仅只是drf的一个第三方扩展且支持Django>=2.0
pip3 install djangorestframework-simplejwt -i https://pypi.douban.com/simple
pip3 install djangorestframework -i https://pypi.douban.com/simple
1.2 settings.py
# 修改配置
INSTALLED_APPS = [
'rest_framework',]
# 修改DRF认证
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',# 使用rest_framework_simplejwt(token)验证身份
'rest_framework.authentication.SessionAuthentication',# 基于用户名密码认证方式
'rest_framework.authentication.BasicAuthentication' # 基于Session认证方式
],'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated' # 默认权限为验证用户
],}
# 修改simplejwt
# simplejwt配置, 需要导入datetime模块
SIMPLE_JWT = {
# token有效时长
'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=30),# token刷新后的有效时间
'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=1),}
1.3 urls.py
from django.contrib import admin
from django.urls import path,include
# 导入 simplejwt 提供的几个验证视图类
from rest_framework_simplejwt.views import (
TokenObtainPairView,TokenRefreshView,TokenVerifyView
)
urlpatterns = [
# Django 后台
path('admin/',admin.site.urls),# DRF 提供的一系列身份认证的接口,用于在页面中认证身份,详情查阅DRF文档
path('api/auth/',include('rest_framework.urls',namespace='rest_framework')),# 获取Token的接口
path('api/token/',TokenObtainPairView.as_view(),name='token_obtain_pair'),# 刷新Token有效期的接口
path('api/refresh/',TokenRefreshView.as_view(),name='token_refresh'),# 验证Token的有效性
path('api/token/verify/',TokenVerifyView.as_view(),name='token_verify'),]
1.4 创建数据库并添加用户
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
1.5 访问路由
1.5.1 获取token
http://127.0.0.1/api/api/token/
1.5.2 校验token
http://127.0.0.1/api/token/verify/
校验成功返回{}
1.5.2 刷新
http://127.0.0.1/api/refresh/
1.6 key介绍
access:用于token失效时,刷新获得新的token
access:就是jwt里面的token
2. 报错AttributeError: 'str' object has no attribute 'decode'
3.2.1 第二种
4.Simple JWT的默认设置
# settings.py
from datetime import timedelta
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),# 访问令牌的有效时间
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),# 刷新令牌的有效时间
'ROTATE_REFRESH_TOKENS': False,# 若为True,则刷新后新的refresh_token有更新的有效时间
'BLACKLIST_AFTER_ROTATION': True,# 若为True,刷新后的token将添加到黑名单中,# When True,'rest_framework_simplejwt.token_blacklist',should add to INSTALLED_APPS
'ALGORITHM': 'HS256',# 对称算法:HS256 HS384 HS512 非对称算法:RSA
'SIGNING_KEY': SECRET_KEY,'VERIFYING_KEY': None,# if signing_key,verifying_key will be ignore.
'AUDIENCE': None,'ISSUER': None,'AUTH_HEADER_TYPES': ('Bearer',),# Authorization: Bearer <token>
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',# if HTTP_X_ACCESS_TOKEN,X_ACCESS_TOKEN: Bearer <token>
'USER_ID_FIELD': 'id',# 使用唯一不变的数据库字段,将包含在生成的令牌中以标识用户
'USER_ID_CLAIM': 'user_id',# 'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',# default: access
# 'TOKEN_TYPE_CLAIM': 'token_type',# 用于存储令牌唯一标识符的声明名称 value:'access','sliding','refresh'
#
# 'JTI_CLAIM': 'jti',#
# 'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',# 滑动令牌是既包含到期声明又包含刷新到期声明的令牌
# 'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),# 只要滑动令牌的到期声明中的时间戳未通过,就可以用来证明身份验证
# 'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),# path('token|refresh',TokenObtainSlidingView.as_view())
}
5.自定义
5.1自定义令牌+返回数据格式
如果你希望在payload部分提供更多信息,比如用户的username,这时你就要自定义令牌(token)了。
5.1.1 seralizers.py
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
"""
自定义令牌
"""
@classmethod
def get_token(cls,user):
token = super(MyTokenObtainPairSerializer,cls).get_token(user)
# Add custom claims
token['logo'] = '爱琉的缘'
return token
def validate(self,attrs):
"""
自定义返回的格式
"""
old_data = super().validate(attrs)
# refresh = self.get_token(self.user)
data = {'status': 1004,'msg': '成功',"token": old_data,# 'refresh': str(refresh),# 'access': str(refresh.access_token)
}
return data
5.1.2 views.py
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework.permissions import AllowAny
from .serializers import MyTokenObtainPairSerializer
class MyObtainTokenPairView(TokenObtainPairView):
permission_classes = (AllowAny,)
serializer_class = MyTokenObtainPairSerializer
5.1.3 urls.py
from django.urls import path,re_path,include
from rest_framework_simplejwt.views import (
TokenObtainPairView,TokenVerifyView
)
from .views import MyObtainTokenPairView
urlpatterns = [
# 刷新Token有效期的接口
path('refresh/token/',# 验证Token的有效性
path('check/token/verify/',]
5.2 自定义认证后台(Backend)
支持手机号/邮箱/账号+密码登录
5.2.1 authenticates.py
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from django.contrib.auth import get_user_model
# 此方法将返回当前活动的用户模型
User = get_user_model()
# print(User)
class MyCustomBackend(ModelBackend):
"""自定义登录,支持用户名,手机,邮箱"""
def authenticate(self,request,username=None,password=None,**kwargs):
try:
user = User.objects.get(Q(username=username) | Q(email=username) | Q(phone=username))
if user.check_password(password):
return user
except Exception as e:
return None
5.2.2 settings.py
# 支持多方式登录
AUTHENTICATION_BACKENDS = ['users.authenticates.MyCustomBackend']
6. jwt解码
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
"""
自定义令牌
"""
def validate(self,attrs):
"""
自定义返回的格式
"""
from django.conf import settings
from jwt import decode as jwt_decode
refresh = self.get_token(self.user)
# str(refresh.access_token) 就是token
decoded_data = jwt_decode(str(refresh.access_token),settings.SECRET_KEY,algorithms=["HS256"])
print(decoded_data) # {'token_type': 'access','exp': 1663135808,'jti': 'fd27374c6ac14d7b85d344979d812b6f','user_id': 1,'logo': '爱琉的缘'}
return data
7. 手动颁发 token
def _make_token(self,user):
"""手动签发token"""
from rest_framework_simplejwt.tokens import RefreshToken
refresh = RefreshToken.for_user(user)
content = {
'refresh': str(refresh),'access': str(refresh.access_token),}
8. 自定义token异常响应
middleware.py 中间件
class ExceptionChange:
def __init__(self,get_response):
self.get_response = get_response
def __call__(self,request):
response = self.get_response(request)
return response
def process_template_response(self,response):
if hasattr(response,'data'):
data = response.data
# print(data)
if isinstance(data,dict) is True:
if "detail" in data.keys():
# 用户名或密码错误
if data.get("detail") == "No active account found with the given credentials":
del response.data["detail"]
response.data["code"] = 402
response.data["msg"] = "用户名或者密码错误!"
# 验证信息过期 token 过期
if data.get("detail") == "此令牌对任何类型的令牌无效":
del response.data["detail"]
del response.data["messages"]
response.data["code"] = 401
response.data["msg"] = "登录已过期,请重新登录"
# 未使用验证信息 未带验证信息请求
if data.get("detail") == "身份认证信息未提供。": # 身份认证信息未提供。
del response.data["detail"]
response.data["code"] = 401
response.data["msg"] = "登录已过期,请重新登录"
# refresh 无效或者过期
if data.get("detail") == "令牌无效或已过期": # 身份认证信息未提供。
del response.data["detail"]
response.data["code"] = 403
response.data["msg"] = "令牌无效或已过期"
return response
在setting中配置
MIDDLEWARE = [
...
'users.middleware.ExceptionChange',]
9. 权限
10. 认证
这是检测Django用户数据库的基本认证方案:
django: 配置为AUTHENTICATION_BACKENDS,
setting.py不写的话,AUTHENTICATION_BACKENDS默认设置为(‘django.contrib.auth.backends.ModelBackend’,),
2. 按照 AUTHENTICATION_BACKENDS 的排列顺序,如果同样的用户名和密码在第一次就匹配了,那么Django将停止处理后面的东西
3. restful: 配置为 DEFAULT_AUTHENTICATION_CLASSES
11. 本文借鉴
(143条消息) djangorestframework-simplejwt入门教程_做我的code吧的博客-CSDN博客
(143条消息) Django REST Framework教程(7): 如何使用JWT认证(神文多图)_大江狗的博客-CSDN博客
djangorestframework-simplejwt简单使用 - 简书 (jianshu.com)(143条消息) DjangoRestFramework 使用 simpleJWT 登陆认证_PFFFei的博客-CSDN博客
原文地址:https://blog.csdn.net/qq_52385631
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。