Django REST framework JWT

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
}

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑猪去兜风z1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值