[ Django-JWT令牌 ]


JWT文档参考

安装

pip install djangorestframework-simplejwt

默认官方提供的三个接口

from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
    TokenVerifyView
)

urlpatterns = [
    ...
    # 通过获取用户传过来的username.pwd, 验证通过返回refresh, access
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),

    # 通过获取传过来的refresh, 返回access
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),

    # 通过获取传来的access, 通过则返回空字典
    path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
    ...
]

重写通过的三个验证接口

  • 重写生成令牌的token加密内容, 与生成令牌时的返回值
  • 重写校验令牌,解密内容返回 序列化&视图
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer, TokenVerifySerializer
from rest_framework_simplejwt.views import TokenObtainPairView, TokenViewBase
from jwt import decode as jwt_decode
from django.conf import settings
import pendulum
import time

# 生成令牌序列号器
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):

    # 令牌内的加密内容token
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        # Add custom claims
        token['username'] = user.username
        token['email'] = user.email
        # print(f'生产令牌的token:"{token}')
        return token

    # 生产令牌返回的数据
    def validate(self, attrs):
        data = super().validate(attrs)

        refresh = self.get_token(self.user)
        data['refresh'] = str(refresh)
        data['access'] = str(refresh.access_token)
        data['username'] = str(refresh.get('username'))
        data['user_id'] = str(refresh.get('user_id'))
        data['email'] = str(refresh.get('email'))
        # print(f'生成令牌的校验data:{data}')
        return data

# 生产令牌视图
class MyTokenObtainPairView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer


def pu_time(b_time):
    try:
        p_t = pendulum.parse(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(b_time)),tz="Asia/Shanghai")
        pendulum.set_locale('zh')
        return p_t.diff_for_humans()
    except Exception as e:
        print(f"时间人性化失败:{e}")
        return f"时间人性化失败:{e}"


# 验证token令牌序列化器
class MyTokenVerifySerializer(TokenVerifySerializer):

    def validate(self, attrs):
        super().validate(attrs)
        decode_data = jwt_decode(attrs['token'], settings.SECRET_KEY, algorithms=["HS256"]) 
        decode_data['exp_time'] = pu_time(decode_data.get('exp')) # 过期时间
        decode_data['ipx_time'] = pu_time(decode_data.get('ixp')) # 生成时间
        decode_data['df_t'] =decode_data.get('exp') - time.time()  # 过期时间差
        return decode_data


# 验证序列号器视图
class MyTokenVerifyView(TokenViewBase):
    serializer_class = MyTokenVerifySerializer



# {
#     "token_type": "access",
#     "exp": 1670753730,    # 令牌过期时间
#     "iat": 1670735727,    # 令牌生成时间
#     "jti": "67b5cc005b2247408acd99db04411fd3",
#     "user_id": 1,
#     "username": "陈海峰",
#     "email": "1743309009@qq.com"
# }