zoukankan      html  css  js  c++  java
  • token认证、JWT

    登录的token操作

    #app.models.py :表结构
    from django.db import models
    class User(models.Model):
        user = models.CharField(max_length=32)
        password = models.CharField(max_length=32)
        def __str__(self):
            return self.user
    class UserToken(models.Model):
        token = models.CharField(max_length=64)
        user = models.OneToOneField(to='User')
        
    #app.objectjson.py :序列化模块
    from rest_framework import serializers
    from app import models
    class UserJson(serializers.ModelSerializer):
        class Meta:
            model = models.User
            fields = '__all__'
    
    #app.views.py 
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from app import models, common, objectjson
    
    
    class Login(APIView):
        def post(self, request):
            data_dic = request.data
            user = models.User.objects.filter(**data_dic).first()
            if user:
                # 登录成功操作token
                token = common.get_token()
                # token的数据库操作,第一次产生token是新建,再次就是更新
                models.UserToken.objects.update_or_create(user=user, defaults={'token': token})
                user_data = objectjson.UserJson(user).data
                return Response({
                    'status': 0,
                    'message': 'login success',
                    'token': token,  # 将token返回给前台
                    'results': user_data
                })
            return Response({
                'status': 1,
                'message': 'login failedr'
            })

    认证方法的实现

    #源码分析
    # as_view()=> APIView.dispatch => self.initial(request,*args,**kwargs) => 封装后的drf的request => request.user => self._authenticate() => authenticate(self,reuquest)的源码根据地
    
    #app.views.py
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.exceptions import AuthenticationFailed
    
    
    class LoginAuthenticate(BaseAuthentication):
        def authenticate(self, request):
            # 登录逻辑:如果用户登录了,登录操作产生了token,且前后台同步了
            # 登录判断:再次发生请求,没有token代表没登录,错误token,代表无效的登录,token正确才是正常的登录用户
            # 如何将token取出,规定token用请求头传递
            token = request.META.get('HTTP_TOKEN')
            result = models.UserToken.objects.filter(token=token).first()
            print(result)
            if result:
                # 认证通过,可以返回None(有多个认证时),可以返回两个值:user,auth
                return result.user, token
            else:
                # 认证失败,抛出APIException或其子类对象
                raise AuthenticationFailed('认证失败')
    
    
    class Books(APIView):
        authentication_classes = [LoginAuthenticate]
    
        # 视图函数处理的逻辑
        def get(self, request):
            # 通过认证后,用request.user拿到当前登录的用户,用request.auth拿到认证值(该值通常自定义)
            print(request.user)
            return Response({
                'status': 0,
                'message': 'ok',
                'results': []
            })

    局部认证

    #app.auth.py 完成校验的所有逻辑
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.exceptions import AuthenticationFailed
    from app import models
    class LoginAuthenticate(BaseAuthentication):
        def authenticate(self, request):
            token = request.META.get('HTTP_TOKEN')
            result = models.UserToken.objects.filter(token=token).first()
            print(result)
            if result:
                return result.user, token
            else:
                raise AuthenticationFailed('认证失败')
    
    class Books(APIView):
      #添加登录认证即可
        authentication_classes = [auth.LoginAuthenticate]
        def get(self, request):
            print(request.user)
            return Response({
                'status': 0,
                'message': 'ok',
                'results': []
            })

    全局认证

    # 1.在settings.py中配置
    # 全局认证
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.SessionAuthentication',
            'rest_framework.authentication.BasicAuthentication',
            'app.auth.LoginAuthenticate'
        ),
    }
    #2.所有的CBV类都不需要添加类属性:authentication_classes
    # 局部禁用 
    # 3.在不需要认证的CBV类中添加类属性:authentication_classes =[]

    注销:在全局认证情况下

    class Logout(APIView):
        # 在全局认证情况下,如果能走get方法,代表已经通过登录认证(登录状态),就可以注销
        def get(self, request):
            models.UserToken.objects.update_or_create(user=request.user, defaults={'token': common.get_token()})
            return Response({
                "status": 0,
                "msg": 'logout success',
            })

    JWT

    # jwt: json web tokens
    # jwt规范:就是对token的规范,头.体.签名
    '''
        1.token一定是后台产生,拥有请求认证,所以要前后台统一
        2.token的组成部分通常有三分部组成:header.payload.signature
        3.header:{"token的加密方式": "base64", "是否有签名": True} 加密处理后的结果
        4.payload:{"账号": *, "密码": *, "发行者": *, "过期时间": *, "浏览器信息": *} 加密处理后的结果
        5.signature:{"header": *, "payload": *, "salt": *} 加密处理后的结果
        
        eg: eyJ0eXAiOiJK.eyJ1c2VyX2lkIjoxLCJ1cNTgzMDM1NDR9.4j5QypLwuf
    '''

    JWT-token操作

    # 安装 djangorestframework-jwt
    #         -- pip3 install djangorestframework-jwt
    
    # 采用 djangorestframework-jwt框架 产生 jwt规范的 token
    from rest_framework_jwt.settings import api_settings
    def get_jwt_token(user):
        # 自定义生成token,基于某user对象,且该user对象必须有username、password两个字段
        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
  • 相关阅读:
    (转)读《从0到1》
    做事需要愿景,产品都是人思想的投射
    sed 替换有单引号的行
    删除iptables nat 规则
    解决yum安装 openssl-devel时产生的Multilib version problems found错误(转)
    docker 私有仓库 harbor docker-compose
    kubernetes 比较好的案例-创建tomcat-mysql集群 mysql.yaml + workpress.yaml
    配虚拟ip脚本
    kubenetes 1.9 学习 pod
    解决sql和beans中名字不一致问题
  • 原文地址:https://www.cnblogs.com/ShenJunHui6/p/10883372.html
Copyright © 2011-2022 走看看