zoukankan      html  css  js  c++  java
  • restframework jwt登录验证

    前言

    • 本套代码借鉴其他博主,大家可去该博主的博客详细了解一下jwt实现流程和具体表现,本文只是做了某些代码的删减。

    • http本身是无状态的,所以无法设置jwt刷新和清除操作,违背了jwt的初衷,但业务需要实现某些功能,比如:退出登录,保持登录有效期等操作时。
      就得借助数据库进行存储,在业务逻辑上进行数据库的操作实现退出登录和刷新token。(以上个人理解,如有不同见解可以提出互相讨论。)

    • 武沛齐的博客地址:https://www.cnblogs.com/wupeiqi/p/11854573.html

    代码实现

    • 首先我们在项目目录下新建utils/jwt_auth.py文件,编写两个函数"生成token"和"校验token"
    import jwt
    import datetime
    from jwt import exceptions
    from mysite.settings import SECRET_KEY      # 配置文件的加密字符串
    from rest_framework import exceptions as es
    
    def create_token(payload, timeout=20):
        """
        生成token
        :param payload:     例如:{'user_id':1,'username':'wupeiqi'}用户信息
        :param timeout:     token的过期时间,默认20分钟
        :return:
        """
        headers = {
            'typ': 'jwt',
            'alg': 'HS256'
        }
    
        # 对传进来的payload字典添加键值对,过期时间
        payload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout)
    
        # 加密
        result = jwt.encode(payload=payload, key=SECRET_KEY, algorithm="HS256", headers=headers).decode('utf-8')
        return result
    
    
    def parse_payload(token):
        """
        校验token并获取payload
        :param token:
        :return:
        """
    
        try:
            verified_payload = jwt.decode(token, SECRET_KEY, True)
        except exceptions.ExpiredSignatureError:
            raise es.AuthenticationFailed({'detail': 'token已失效'})
        except jwt.DecodeError:
            raise es.AuthenticationFailed({'detail': 'token认证失败'})
        except jwt.InvalidTokenError:
            raise es.AuthenticationFailed({'detail': '非法的token'})
    
        return verified_payload
    
    
    • 新建utils/auth.py文件,在该文件中编写我们自定义的认证组件,
      必须继承restframework中的认证类BaseAuthentication
    from rest_framework.authentication import BaseAuthentication
    from rest_framework import exceptions
    from polls.utils.jwt_auth import parse_payload
    
    
    class JwtAuthorizationAuthentication(BaseAuthentication):
        """
        用户需要通过请求头的方式来进行传输token
        """
    
        def authenticate(self, request):
    
            # 这里选择从请求头方式获取token
            authorization = request.META.get('HTTP_AUTHORIZATION', '')
            auth = authorization.split()
            if not auth:
                raise exceptions.AuthenticationFailed({'detail': '未获取到Authorization请求头'})
            if auth[0].lower() != 'jwt':
                raise exceptions.AuthenticationFailed({'detail': "Authorization请求头中认证方式错误"})
    
            if len(auth) == 1:
                raise exceptions.AuthenticationFailed({'detail': "非法Authorization请求头"})
            elif len(auth) > 2:
                raise exceptions.AuthenticationFailed({'detail': "非法Authorization请求头"})
    
            token = auth[1]
            result = parse_payload(token)
    
            # 如果想要request.user等于用户对象,此处可以根据payload去数据库中获取用户对象。
            return (result, token)
    
    
    • 我们需要在settings.py全局配置文件中加入我们的认证组件作为全局认证
      每条请求必须携带token并通过认证才能进入视图函数。
    REST_FRAMEWORK = {
        # 全局使用认证类
        #注意里面是路径,将认证类写在utils文件夹的auth.py中,'api'填写你项目目录
        "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.JwtAuthorizationAuthentication', ],
    }
    
    • 像我们的登录/注册是不需要认证的,我们可以在视图中屏蔽认证。
    class LoginView(APIView):
        authentication_classes = []
        ......
    
  • 相关阅读:
    导出api文档
    Webservice测试从头来
    Java8新特性【转】
    spring获取bean的时候严格区分大小写
    java static 方法使用笔记
    maven Spring获取不到配置文件
    4月22日
    4月21日
    9月20日
    9月18日
  • 原文地址:https://www.cnblogs.com/se7enjean/p/13187788.html
Copyright © 2011-2022 走看看