首页 > 其他分享 >djangorestframework-simplejwt 的使用

djangorestframework-simplejwt 的使用

时间:2024-02-19 12:56:27浏览次数:28  
标签:token rest framework djangorestframework user 使用 simplejwt import refresh

djangorestframework-simplejwt使用

转载于:https://www.cnblogs.com/liuqingzheng/p/17942227

1 快速使用

1.1 配置

# 1 安装
pip install djangorestframework-simplejwt

# 2 路由层
from rest_framework_simplejwt.views import token_obtain_pair, token_verify, token_refresh

urlpatterns = [
    path('login/', token_obtain_pair),
    path('verify/', token_verify),
    path('refresh/', token_refresh),
]

# 3 配置文件
import datetime
SIMPLE_JWT = {
    # token有效时长
    'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=30),
    # token刷新后的有效时间
    'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=1),
}

# 4 注册app
INSTALLED_APPS = [
    ...
    'rest_framework_simplejwt',
    ...
]

# 5 迁移表,创建超级用户
	createsuperuser

1.2 测试

http://127.0.0.1:8000/login/

image

http://127.0.0.1:8000/verify/

image

http://127.0.0.1:8000/refresh/

image

1.3 认证

from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
class BookView(APIView):
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    def get(self,request):
        return Response("ok")

image

2 Simple JWT的默认设置

# JWT配置
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),  # Access Token的有效期
    'REFRESH_TOKEN_LIFETIME': timedelta(days=7),  # Refresh Token的有效期
    
    # 对于大部分情况,设置以上两项就可以了,以下为默认配置项目,可根据需要进行调整
    
    # 是否自动刷新Refresh Token
    'ROTATE_REFRESH_TOKENS': False,  
    # 刷新Refresh Token时是否将旧Token加入黑名单,如果设置为False,则旧的刷新令牌仍然可以用于获取新的访问令牌。需要将'rest_framework_simplejwt.token_blacklist'加入到'INSTALLED_APPS'的配置中
    'BLACKLIST_AFTER_ROTATION': False,  
    'ALGORITHM': 'HS256',  # 加密算法
    'SIGNING_KEY': settings.SECRET_KEY,  # 签名密匙,这里使用Django的SECRET_KEY
    # 如为True,则在每次使用访问令牌进行身份验证时,更新用户最后登录时间
    "UPDATE_LAST_LOGIN": False, 
    # 用于验证JWT签名的密钥返回的内容。可以是字符串形式的密钥,也可以是一个字典。
    "VERIFYING_KEY": "",
    "AUDIENCE": None,# JWT中的"Audience"声明,用于指定该JWT的预期接收者。
    "ISSUER": None, # JWT中的"Issuer"声明,用于指定该JWT的发行者。
    "JSON_ENCODER": None, # 用于序列化JWT负载的JSON编码器。默认为Django的JSON编码器。
    "JWK_URL": None, # 包含公钥的URL,用于验证JWT签名。
    "LEEWAY": 0, # 允许的时钟偏差量,以秒为单位。用于在验证JWT的过期时间和生效时间时考虑时钟偏差。
    # 用于指定JWT在HTTP请求头中使用的身份验证方案。默认为"Bearer"
    "AUTH_HEADER_TYPES": ("Bearer",), 
    # 包含JWT的HTTP请求头的名称。默认为"HTTP_AUTHORIZATION"
    "AUTH_HEADER_NAME": "HTTP_AUTHORIZATION", 
     # 用户模型中用作用户ID的字段。默认为"id"。
    "USER_ID_FIELD": "id",
     # JWT负载中包含用户ID的声明。默认为"user_id"。
    "USER_ID_CLAIM": "user_id",
    
    # 用于指定用户身份验证规则的函数或方法。默认使用Django的默认身份验证方法进行身份验证。
    "USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
    #  用于指定可以使用的令牌类。默认为"rest_framework_simplejwt.tokens.AccessToken"。
    "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
    # JWT负载中包含令牌类型的声明。默认为"token_type"。
    "TOKEN_TYPE_CLAIM": "token_type",
    # 用于指定可以使用的用户模型类。默认为"rest_framework_simplejwt.models.TokenUser"。
    "TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
    # JWT负载中包含JWT ID的声明。默认为"jti"。
    "JTI_CLAIM": "jti",
    # 在使用滑动令牌时,JWT负载中包含刷新令牌过期时间的声明。默认为"refresh_exp"。
    "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
    # 滑动令牌的生命周期。默认为5分钟。
    "SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
    # 滑动令牌可以用于刷新的时间段。默认为1天。
    "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
    # 用于生成访问令牌和刷新令牌的序列化器。
    "TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",
    # 用于刷新访问令牌的序列化器。默认
    "TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
    # 用于验证令牌的序列化器。
    "TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
    # 用于列出或撤销已失效JWT的序列化器。
    "TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",
    # 用于生成滑动令牌的序列化器。
    "SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",
    # 用于刷新滑动令牌的序列化器。
    "SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
}

3 自定义返回格式

#1 编写序列化类

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView


class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token['name'] = user.username
        return token

    def validate(self, attrs):
        """
        自定义返回的格式
        """
        old_data = super().validate(attrs)
        refresh = self.get_token(self.user)
        data = {'code': 100,
                'msg': '登录成功成功',
                'username':self.user.username,
                'refresh': str(refresh),
                'access': str(refresh.access_token)
                }
        return data

# 2 配置文件配置
SIMPLE_JWT = {
  "TOKEN_OBTAIN_SERIALIZER": "app01.serializers.MyTokenObtainPairSerializer",
}

4 多方式登录

4.1 models.py

# 需要扩写auth的User表,增加手机号字段
# 配置文件配置

4.2 路由

from app01.views import LoginView
urlpatterns = [
    path('mul_login/', LoginView.as_view()),
]

4.3 视图类

from rest_framework.response import Response
from . import serializers

class LoginView(APIView):
    def post(self, request, *args, **kwargs):
        serializer = serializers.LoginSerializer(data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        refresh = serializer.context.get('refresh')
        access = serializer.context.get('access')
        return Response({'code': 100, 'msg': '登录成功', 'refresh': refresh, 'access': access})

4.4 序列化类

from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework.exceptions import ValidationError
from rest_framework_simplejwt.tokens import RefreshToken


class LoginSerializer(serializers.ModelSerializer):
    # 登录请求,走的是post方法,默认post方法完成的是create入库校验,所以唯一约束的字段,会进行数据库唯一校验,导致逻辑相悖
    # 需要覆盖系统字段,自定义校验规则,就可以避免完成多余的不必要校验,如唯一字段校验
    username = serializers.CharField()

    class Meta:
        model = User
        # 结合前台登录布局:采用账号密码登录,或手机密码登录,布局一致,所以不管账号还是手机号,都用username字段提交的
        fields = ('username', 'password')

    def validate(self, attrs):
        user = self._get_user(attrs)
        refresh = RefreshToken.for_user(user)
        self.context['refresh'] = str(refresh)
        self.context['access'] = str(refresh.access_token)
        return attrs

    # 多方式登录
    def _get_user(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        import re
        if re.match(r'^1[3-9][0-9]{9}$', username):
            # 手机登录
            user = User.objects.filter(mobile=username, is_active=True).first()
        elif re.match(r'^.+@.+$', username):
            # 邮箱登录
            user = User.objects.filter(email=username, is_active=True).first()
        else:
            # 账号登录
            user = User.objects.filter(username=username, is_active=True).first()
        if user and user.check_password(password):
            return user

        raise ValidationError({'user': 'user error'})

4.5 测试

image

5 自定义用户表,手动签发和认证

5.1 签发

表模型

class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)

路由

from app01.views import MyLoginView
urlpatterns = [
    path('my_login/', MyLoginView.as_view()),
]

视图类

class MyLoginView(APIView):
    def post(self, request, *args, **kwargs):
        serializer = serializers.MyLoginSerializer(data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        refresh = serializer.context.get('refresh')
        access = serializer.context.get('access')
        return Response({'code': 100, 'msg': '登录成功', 'refresh': refresh, 'access': access})

序列化类

from rest_framework import serializers
from .models import UserInfo
from rest_framework.exceptions import ValidationError
from rest_framework_simplejwt.tokens import RefreshToken


class MyLoginSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserInfo
        fields = ('username', 'password')

    def validate(self, attrs):
        user = self._get_user(attrs)
        refresh = RefreshToken.for_user(user)
        self.context['refresh'] = str(refresh)
        self.context['access'] = str(refresh.access_token)
        return attrs

    # 多方式登录
    def _get_user(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')

        user = UserInfo.objects.filter(username=username, password=password).first()
        if not user:
            raise ValidationError({'user': 'user error'})
        return user

image

image

5.2 认证

认证类

from .models import UserInfo
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from rest_framework_simplejwt.authentication import JWTAuthentication


class MyJSONWebTokenAuthentication(JWTAuthentication):
    def authenticate(self, request):
        jwt_value = request.META.get("HTTP_TOKEN")
        if not jwt_value:
            raise AuthenticationFailed('token 字段是必须的')
        validated_token = self.get_validated_token(jwt_value)
        print(validated_token['user_id'])
        user = UserInfo.objects.filter(pk=validated_token['user_id']).first()
        return user, jwt_value
    
    
#### 或者
from rest_framework_simplejwt.tokens import AccessToken
class MyJSONWebTokenAuthentication(BaseAuthentication):
    def authenticate(self, request):
        jwt_value = request.META.get("HTTP_TOKEN")
        if not jwt_value:
            raise AuthenticationFailed('token 字段是必须的')
        validated_token = AccessToken(jwt_value)
        print(validated_token['user_id'])
        user = UserInfo.objects.filter(pk=validated_token['user_id']).first()
        return user, jwt_value

视图类

from .auth import MyJSONWebTokenAuthentication
class BookView(APIView):
    authentication_classes = [MyJSONWebTokenAuthentication]
    # permission_classes = [IsAuthenticated]

    def get(self, request):
        print(request.user.username)
        return Response("ok")

标签:token,rest,framework,djangorestframework,user,使用,simplejwt,import,refresh
From: https://www.cnblogs.com/Edmondhui/p/18020833

相关文章

  • selenium使用已打开的浏览器
    最后更新:2024.02.19python版本:3.12selenium版本:4.16.0在写selenium的时候,调试网页每次都需要新建一个浏览器实例,再打开网页进行操作,比较费时,尤其是在当网页加载特别慢的情况下;使用 ChromeDevTools协议就可以让selenium直接使用当前已经打开的处于远程调试的浏览器实例,以下......
  • 远程控制软件RustDesk自建服务器全平台部署及使用教程
    RustDesk挺出名的一款远程控制,远程协助的开源软件。完美替代TeamViewer,ToDesk,向日葵等平台。关键支持自建服务器,更安全私密远程控制电脑!其中客户端支持安卓,且支持控制安卓手机。官方地址官网:https://rustdesk.com/开源地址:https://github.com/rustdesk/一、准备工作1,有自己......
  • 使用 Visual Studio 断点调试 DLL
    继上文说到使用IDA和WinDbg调试无dmp文件  那么在有源码的情况下可以直接断点调试DLL,目的是查看DLL内部的函数调用场景:程序执行到某个DLL时突然崩溃,先确定Debug生成的DLL在程序中运行是否也会有闪退如果有,则适用于VS断点调试操作步骤:在Debug下生成一......
  • 系统使用日常
    PID4占用80端口HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Start值改为0->reboot依然被占用,继续以下操作netshhttpshowservicestate->查找关联进程ID->找到对应服务->禁用Windows11跳过登录微软账号方法一:SHIFT+F10 -> oobe\bypassnro.cmd -> ......
  • Filezilla Server 使用教程
    FilezillaServer使用教程FileZillaServer是一款免费开源的FTP服务器端架设程序,使用FileZillaServer你可以轻轻松松在你的服务器开设ftp,下面演示用FileZillaServer来建立服务器上各网站的ftp。步骤1、首先下载好FilezillaServer软件,点进去下载即可,如图所示: 将下载好的Fil......
  • Django——admin创建和使用
    1.创建admin#1.创建命令pythonmanage.pycreatesuperuser#2.输入管理员用户名Username(leaveblanktouse'administrator'):#3.输入邮箱Emailaddress:#4.输入密码Password:#5.确认密码Password(again):#6.确认提示Superusercreatedsuccessfully.2.后期......
  • Detours 的使用
    Detours是一个用于在ARM,ARM64,X86,X64和IA64机器上拦截二进制函数的库。Detours最常用来拦截应用程序中的win32api调用,比如添加调试工具。拦截代码在运行时动态应用。Detours将目标函数的前几个指令替换为无条件跳转到用户提供的detour函数它与 WriteProcess......
  • 免费xshell和xftp下载使用
    背景:最近xshell老是跳出提示说要更新,于是最终没忍住,就更新了,下班后关了机,今天一点进去的时候,不能用了!网上搜了搜,有说提供xshell激活秘钥的,有提供百度网盘地址让我下载的,折腾一通下来,我的C盘不知道咋就红了,还时不时冒出来一些游戏的页面。忍住,忍住没去找师父,然后找到了师父之前......
  • 多线程系列(二) -Thread类使用详解
    一、简介在之前的文章中,我们简单的介绍了线程诞生的意义和基本概念,采用多线程的编程方式,能充分利用CPU资源,显著的提升程序的执行效率。其中java.lang.Thread是Java实现多线程编程最核心的类,学习Thread类中的方法,是学习多线程的第一步。下面我们就一起来看看,创建线程的几种......
  • 熟练使用有棱有角的内存
    内存IC中邮电源,地址信号,数据信号,控制信号等用于输入输出的大量引脚(IC的引脚),通过为其指定地址(address),来进行数据的读写。现在大家使用的计算机至少有512M的内存。这就相当于512000个(512MB÷1KB=512K)1KB的内存IC。当然一台计算机中不大可能放入如此多的内存IC。通常情况下计算机......