首页 > 其他分享 >simple-jwt的简单使用

simple-jwt的简单使用

时间:2024-05-04 22:23:04浏览次数:17  
标签:get simple self jwt refresh token user 简单 serializer

【一】安装

pip install djangorestframework-simplejwt

【二】配置

# settings.py
INSTALLED_APPS = [
	...
    'rest_framework',               # add
    'rest_framework_simplejwt',     # add
]

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}
SIMPLE_JWT = {
    # token有效时长(返回的 access 有效时长)
    'ACCESS_TOKEN_LIFETIME': datetime.timedelta(seconds=30),
    # token刷新的有效时间(返回的 refresh 有效时长)
    'REFRESH_TOKEN_LIFETIME': datetime.timedelta(seconds=20),
}

【三】配置路由

# urls.py
urlpatterns = [
    # 登录
    path('login/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    path('verify/', TokenVerifyView.as_view(), name='token_verify'),
]

【四】配置认证类

# 导入这两个类
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.permissions import IsAuthenticated


class CarView(ModelViewSet):
    serializer_class = CarSerializer
    queryset = CarModel.objects.all()
    # 认证类和权限类需要搭配使用
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

【五】内置user表

​ 如果用内置的user表的话,此时直接以 path('login/', TokenObtainPairView.as_view(), name='token_obtain_pair'),登入就会签发token,

​ 需要在请求头加上Authorization,格式:Bearer [token值] 有空格

【六】自定义返回内容

​ 如果需要自定义登录后返回的消息的话,就需要进行如下配置

【1】序列化类

继承TokenObtainPairSerializer

重写validate方法

定制data返回,即为返回消息

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer

# 序列化类 继承TokenObtainPairSerialize
class AutoLoginSerializer(TokenObtainPairSerializer):
    # 重写父类的全局钩子
    def validate(self, attrs):
        dic = super().validate(attrs)
        data = {
            'code': 100,
            'message': '登陆成功',
            'username': self.user.username,
            'refresh': dic.get('refresh'),
            'access': dic.get('access')
        }
        return data

【2】视图类

如果不是继承内置user表的话,就需要进行如下配置

# 视图类
class AutoUserView(GenericViewSet):
    serializer_class = AutoLoginSerializer

    @action(methods=['POST'], detail=False)
    def login(self, request):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            return Response(serializer.validated_data)

【3】JWT配置

由于自己定义了序列化类,所以需要在配置项里面替换默认的序列化类为自己定义的序列化类

# JWT配置 里面具体配置可以参考文档
SIMPLE_JWT = {
    # 用于生成access和刷refresh的序列化器。
    "TOKEN_OBTAIN_SERIALIZER": "app02.serializer.AutoLoginSerializer",
}

【七】定制payload内容

自定义序列化类

继承TokenObtainPairSerializer

重写get_token,继承父类的get_token

修改get_tokend的返回值的内容

返回新的值

class AutoLoginSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        # 往第二段数据里面加东西 这里加一个名字
        token['name'] = user.username
        return token

    # 重写全局钩子
    def validate(self, attrs):
        dic = super().validate(attrs)
        data = {
            'code': 100,
            'message': '登陆成功',
            'username': self.user.username,
            'refresh': dic.get('refresh'),
            'access': dic.get('access')
        }

        return data

【八】多方式登录

​ 可以通过多种方式登录,如用户名/手机号/邮箱

【1】视图类

class UserView(GenericViewSet, CreateModelMixin):
    serializer_class = None

    def get_serializer_class(self):
        if self.action == 'login':
            return UserLSerializer
        else:
            return UserRSerializer

    @action(methods=['POST'], detail=False)
    def register(self, request):
        res = super().create(request)
        return Response({'code': 200, 'message': '注册成功', 'result': res.data})

    @action(methods=['POST'], detail=False)
    def login(self, request):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            refresh = serializer.context.get('refresh')
            access = serializer.context.get('access')
            return Response({'code': 200, 'message': '登录成功', 'refresh': refresh, 'access': access})
        return Response(serializer.errors)

【2】序列化类

class UserLSerializer(serializers.Serializer):
    # 因为登录的时候只输入用户名密码
    # 所以只需要序列化两个字段
    username = serializers.CharField()
    password = serializers.CharField()

    # 这个方法用来拿到登录对象
    def _get_user(self, attrs):
        # 手机号正则表达式
        phone_regex = r'^1[3-9]\d{9}$'
        # 邮箱正则表达式
        email_regex = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
        # 拿到 手机号/邮箱/用户名
        username = attrs.get('username')
        # 拿到密码
        password = attrs.get('password')
        # 下面分别做判断 看用户名是以什么方式登录
        if re.match(phone_regex, username):
            user = User.objects.filter(mobile=username).first()
        elif re.match(email_regex, username):
            user = User.objects.filter(email=username).first()
        else:
            user = User.objects.filter(username=username).first()
        if user and user.check_password(password):
            return user


    def validate(self, attrs):
        user = self._get_user(attrs)
        # 如果上面验证失败user就为None,就抛异常
        if not user:
            raise ValidationError('用户名或密码错误')
        refresh = RefreshToken.for_user(user)
        self.context['refresh'] = str(refresh)
        self.context['access'] = str(refresh.access_token)
        return attrs

【九】自定义用户表 签发

​ 如果不使用内置的user表作为用户表,那么就需要手动签发token以及手动认证

【1】视图类

手动写登录注册接口

class NormaUserView(GenericViewSet, CreateModelMixin):
    serializer_class = None

    def get_serializer_class(self):
        if self.action == 'login':
            return NormalUserLSerializer
        else:
            return NormalUserRSerializer

    @action(methods=['POST'], detail=False)
    def register(self, request):
        res = super().create(request)
        return Response({'code': 200, 'message': '注册成功', 'result': res.data})

    @action(methods=['POST'], detail=False)
    def login(self, request):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            refresh = serializer.context.get('refresh')
            access = serializer.context.get('access')
            return Response({'code': 200, 'message': '登录成功', 'refresh': refresh, 'access': access})
        return Response(serializer.errors)

【2】序列化类

手动签发token

导入RefreshToken类

调用RefreshToken类的for_user方法传入登录user对象

获取token,传入上下文管理器context

class NormalUserLSerializer(serializers.Serializer):
    username = serializers.CharField()
    password = serializers.CharField()

    def _get_user(self, attrs):
        # 拿到 手机号/邮箱/用户名
        username = attrs.get('username')
        # 拿到密码
        password = attrs.get('password')
        user = NormalUser.objects.filter(username=username, password=password).first()
        print(user)
        return user

    def validate(self, attrs):
        user = self._get_user(attrs)
        if not user:
            raise ValidationError('用户名或密码错误')
        token = RefreshToken.for_user(user)
        access = str(token.access_token)
        refresh = str(token)
        self.context['access'] = access
        self.context['refresh'] = refresh
        return attrs

【十】自定义用户表 认证

导入JWTAuthentication类from rest_framework.exceptions import AuthenticationFailed

写认证类继承JWTAuthentication类

重写authenticate方法

获取token

调用父类get_validated_token以此校验token

from rest_framework.exceptions import AuthenticationFailed

# 继承JWTAuthentication
class CommonAuthentication(JWTAuthentication):
    # 重写authenticate
    def authenticate(self, request):
        # 从请求头中取出token
        token = request.META.get('HTTP_AUTHORIZATION')
        # 如果没有token就说明没有登录,所以抛出异常
        if not token:
            raise AuthenticationFailed('请先登录再操作')
        # 调用父类get_validated_token以此校验token,返回值是payload段,包含用户id
        validated_token = self.get_validated_token(token)
        # 取到id,从而得到用户对象
        user_id = validated_token.get('user_id')
        user = NormalUser.objects.filter(pk=user_id).first()
        return user, token

标签:get,simple,self,jwt,refresh,token,user,简单,serializer
From: https://www.cnblogs.com/Hqqqq/p/18172849

相关文章

  • python - Counter简单使用
    统计元素数量,并返回字典,键为元素,值为个数fromcollectionsimportCounterlst=['a','b','c','d','a','b','a','c','c','c']dic=Counter(lst)print(dic)#Counter({'c......
  • docker简单笔记
     这里不说基础概念的东西,直接上车出发 指令 docker-compose--help docker-composeup   会自动下载运行依赖,然后跑到容器隔离环境中docker-composedown--rmiall   删除由DockerCompose管理的所有容器 安装(我的版本20.10.5) 简单例子 如果遇......
  • 我的SimpleMemory博客设置
    博客皮肤选择SimpleMemory行号和Mac风格均不选博客侧边栏公告:<scripttype="text/javascript">window.cnblogsConfig={info:{name:'pangyou3s',//用户名startDate:'2023-01-24',//入园时间,年-月-日。入园时间查看方法:鼠标停留园龄时......
  • Oracle23ai 数据库的简单验证
    Oracle23ai数据库的简单验证背景2024年5.1期间发现有公众号再说Oracle23c使用容器方式进行安装的感觉可以试用把玩一下.简单安装dockerpullcontainer-registry.oracle.com/database/free:latest运行timedockerrun-d--nameoracle23ai-horacle23ai\--net......
  • dbt show 命令处理简单说明
    dbtshow主要做以下事情内部处理编译基于sql的model,test,analysis,或者执行基于--inline的sql,当前不支持python模型在dw中执行查询在终端中预览结果备注:默认limit为5,但是可以自己调整通过--limit参数,同时dbtshow使用的一直是最新的数据以及编译模型,不会使用物化的......
  • 基于有限体积法和交错网格的SIMPLE算法推导及实现
    基于有限体积法和交错网格的SIMPLE算法推导及实现SIMPLE算法,半隐式速度压力耦合算法,是专门求解不可压流体流动的算法。由于不可压流体控制方程中,密度常常被视为常数,没有表征流体密度、压力、温度联系的状态方程,压力以梯度项的形式存在于动量方程中,无法显性表达或者直接求解,造成了......
  • 策略模式简单运用
    策略模式简单运用背景是根据不同的渠道,处理不同的任务,相比ifelse可以不用动主逻辑代码,代码可维护性好点,每次处理不同渠道的任务只需要改对应的实现,缺点就是的增加类的数量,核心就是多态。1.定义接口publicinterfaceTaskFileHandleService{/***获取任务类......
  • [web]cookie session和token(jwt)
    cookie:用户登录后,服务器生成一个cookie返回,并要求浏览器set-cookie,存储一下,下次访问时带上cookie,即可区分用户cookie可以被篡改session:信息存储在服务端,客户端cookie中存一个sessionid服务端有额外的存储成本负载均衡需要考虑session共享查询session是查库操作,耗时高......
  • 类模板的简单应用(用于存储不同类型数据的类容器)
    类模板应用explicitexplicit是一个关键字,用于指定该构造函数是显式构造函数。在C++中,当一个类的构造函数只有一个参数时,它可以被用于隐式类型转换,这可能会导致意想不到的行为和潜在的错误。为了避免这种情况,可以使用explicit关键字来声明该构造函数,表示禁止隐式类型转换,只能......
  • LDAP简单介绍及使用
    前言随着企业内部各种开源平台越来越多,例如:gitlab、Jenkins、JumpServer、Rancher等,账号维护变成一件繁琐的事情,这时需要一个统一账号维护的平台,每人只需一个账号,在公司内部平台通用。而大多数开源平台都支持LDAP,因此只要搭建好LDAP服务,将企业内部这些平台都对接到LDAP,即可实......