0. 官方已经弃用,不在更新
- 最新版的django(4x系列)无法在使用jwt,
- 其开发者推荐的替代品为Simple JWT(djangorestframework-simplejwt)
django-rest-framework-jwthttps://github.com/jpadilla/django-rest-framework-jwt
- 其替代物
Simple JWT(djangorestframework-simplejwt)https://juejin.cn/post/6970308794672906271
1. 安装
pip3 install djangorestframework-jwt -i https://mirrors.aliyun.com/pypi/simple/
2. 手动使用
2.1 重写认证
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from rest_framework_jwt.authentication import jwt_decode_handler
import jwt
from app01 import models
class JWTAuthentication(BaseAuthentication):
def authenticate(self, request):
jwt_value = request.META.get('HTTP_AUTHORIZATION')
if not jwt_value:
# 没有值,直接抛异常
raise AuthenticationFailed('您没有携带认证信息')
if jwt_value:
try:
# jwt提供了通过三段token,取出payload的方法,并且有校验功能
payload = jwt_decode_handler(jwt_value)
except jwt.ExpiredSignature:
raise AuthenticationFailed('签名过期')
except jwt.InvalidTokenError:
raise AuthenticationFailed('用户非法')
except Exception as e:
# 所有异常都会走到这
raise AuthenticationFailed(str(e))
# 因为payload就是用户信息的字典
# 传进去一个对象,自动构建成下列的字典信息
# payload {'user_id': 1, 'username': 's1', 'exp': 1652945457, 'orig_iat': 1650180657}
# print("payload", payload)
user = models.UserInfo.objects.get(pk=payload.get('user_id'))
# print('user', user)
return user, jwt_value
2.2 配置
# jwt
import datetime
REST_FRAMEWORK = {
'UNAUTHENTICATED_USER': None, # 如果没有token,request.user显示的是None,不在是匿名用户(AnonymousUser)
'UNAUTHENTICATED_TOKEN': None, # 如果没有token,request.auth显示的是None,默认就是None
'DEFAULT_AUTHENTICATION_CLASSES': [
'utils.common.auth.JWTAuthentication',
],
}
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=32), # 设置过期时间
'JWT_ALLOW_REFRESH': True, # 请求来时,自动刷新token
}
2.3 视图(手动签发token)
from rest_framework.views import APIView
from rest_framework.response import Response
from . import models
from .auth import JWTAuthentication
def get_token(user):
from rest_framework_jwt.settings import api_settings
# 生成token
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
return token
class T1(APIView):
authentication_classes = []
def get(self, request):
user = models.UserInfo.objects.filter(username='s1').first()
print(user)
token = get_token(user=user)
data = {
"msg": "ok",
"token": token
}
return Response(data=data)
class T2(APIView):
# 进行使用
authentication_classes = [JWTAuthentication, ]
def get(self, request):
print(request.user)
ret = models.UserInfo.objects.all().first()
username = ret.username
return Response(username)
"""
使用
http://127.0.0.1:8000/t2/
djangorestframework-jwt 1.11.0
在请求头里面(最新版的无需在
JWT )
authorization:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.e
"""
2.4 手动签发token
def get_token(user):
from rest_framework_jwt.settings import api_settings
# 生成token
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
return token
3. 自动校验+自定义返回格式(无法实现)
3.1 自动校验,并签发
from rest_framework_jwt.views import refresh_jwt_token
# token校验
path('verify_token/', refresh_jwt_token), # RefreshJSONWebToken 校验并更新
3.2 接口
from rest_framework.views import APIView
from rest_framework.response import Response
from . import models
from .auth import JWTAuthentication
def get_token(user):
from rest_framework_jwt.settings import api_settings
# 生成token
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
return token
class T1(APIView):
authentication_classes = []
def get(self, request):
user = models.UserInfo.objects.filter(username='s1').first()
print(user)
token = get_token(user=user)
data = {
"msg": "ok",
"token": token
}
return Response(data=data)
class T2(APIView):
# 进行使用
authentication_classes = [JWTAuthentication, ]
def get(self, request):
print(request.user)
ret = models.UserInfo.objects.all().first()
username = ret.username
return Response(username)
"""
使用
http://127.0.0.1:8000/t2/
在请求头里面(最新版的无需在使用JWT )
Authorization:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.e
"""
3.3 自定义返回类型
3.3.1 view
def jwt_response_payload_handler(token, user=None, request=None):
"""
自定义jwt认证成功返回数据
token: jwt 字符串
user: 当前登录用户对象
request: 当前请求对象
"""
user_id = user.id
conn = get_redis_connection('cart')
cart_length = conn.hlen(user_id)
return {
'token': token,
'id': user_id,
'username': user.username,
'cart_length': cart_length,
'credit': user.credit,
'credit_to_money': settings.CREDIT_TO_MONEY,
}
3.3.2 settings
import datetime
# 用户自定义返回类型
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=32), # 设置过期时间
'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler',
'JWT_ALLOW_REFRESH': True, # 请求来时,自动刷新token
}