zoukankan      html  css  js  c++  java
  • 34.django使用jwt

    1.jwt

    这里是打包的代码地址jwt代码包

    json web token:用于用户认证(前后端分离/微信小程序/app开发)
    - 基于传统的token认证
    	用户登录,服务端给返回token,并将token(服务端不保存)
        以后用户再来访问时,需要携带token,服务端获取token后,再去数据库中获取token
    - jwt
    	用户登陆之后,服务端给用户返回一个token(服务器不保存)
        以后用户访问,都需要带着token,服务器获取token后,通过算法进行token验证
    
    优势:相较于传统的token相比,他无需在服务端保存token
    

    2.jwt实现过程

    1.提交用户名和密码给服务端,如果登录成功,使用jwt生成一个token值,并返回给用户
    
    注意:jwt生成的token是由三段字符串通过.连接起来的
    
    第一段字符串:HEADER,内部包含算法token类型。
    json转化成字符串,然后做base64url加密(base64加密;+-)
    {
        "alg": "HS256",
        'type': "JWT"
    }
    第二段字符串:payload,自定义值:
    json转化成字符串,然后做base64url加密(base64加密;+-)
    {
        'id': "124124",
        'name':'chengge',
        'exp': '1423434132',# 超时时间
    }
    第三段字符串:
    第一步:将第1,2不封密文拼接起来
    第二步:对前两部分密文进行hs256加密+加盐
    第三步:对hs256加密后的密文在做base64url加密
    
    - 以后用户来访问时候,携带token,后端需要对token进行校验
    	- 获取token
        - 第一步:对token进行切割
        - 第二步:把第二段进行base64解密,并获取payload信息,检测超市时间
     	- 第二步:把第一个段拼接再次执行hs256加密+加盐
        
        密文 = base64解密
        如果密文相等表示token没有被修改过
    

    3.应用

    pip install pyjwt
    pyjwt.encode 生成token
    pyjwt.decode token解密
    

    4.扩展

    pip install djagnrestframework-jwt
    djagnrestframework-jwt 本质上是调用pyjwt实现的
    

    版本一:

    原理就是服务端保存tokne

    class LoginView(APIView):
        '''用户登录'''
        def post(self, request, *args, **kwargs):
            username = request.data.get("username")
            passwork = request.data.get("password")
            user_obj = models.UserInfo.objects.filter(username=username, password=passwork).first()
            if not user_obj:
                return Response({"code": 1000, 'error': '用户名或密码错误'})
            random_string = str(uuid.uuid4())
            user_obj.token = random_string
            user_obj.save()
            return Response({"code":1001, 'data': '登陆成功'})
    
    
    class OrderView(APIView):
        def get(self, request, *args, **kwargs):
            token = request.query_params.get("token")
            print(token)
            if not token:
                Response({"code": 1003, 'error': '未登录失败'})
            user_obj = models.UserInfo.objects.filter(token=token).exists()
            if not user_obj:
                Response({"code": 1003, 'error': '未登录失败'})
            return Response("订单列表")
    

    版本二:

    通过jwt进行验证,但是发现每个函数都要使用太麻烦了

    class JwtLoginView(APIView):
        '''用户登录'''
        def post(self, request, *args, **kwargs):
            username = request.data.get("username")
            passwork = request.data.get("password")
            user_obj = models.UserInfo.objects.filter(username=username, password=passwork).exists()
            if not user_obj:
                return Response({"code": 1000, 'error': '用户名或密码错误'})
    
    
            import jwt
            import datetime
            salt = "fadsf$@%#%#%gsfdgsdgfd"
            headers = {
                "typ": "jwt_",
                "alg": "HS256",
            }
            payload = {
                "user_id": 1,
                "username": "alex",
                "exp": datetime.datetime.utcnow() + datetime.timedelta(minutes=1)
            }
    
            token = jwt.encode(payload=payload, key=salt, headers=headers).decode("utf-8")
            return Response({"code":1001, 'data': token})
    
    
    class JwtOrderView(APIView):
        def get(self, request, *args, **kwargs):
            # 获取token并验证
            token = request.query_params.get("token")
            import jwt
            from jwt import exceptions
            result = None
            msg = None
            salt = "fadsf$@%#%#%gsfdgsdgfd"
            try:
                result = jwt.decode(token, salt, True)
            except exceptions.ExpiredSignatureError:
                msg = "token失效"
    
            except exceptions.DecodeError:
                msg = "token认证失败"
            except exceptions.InvalidTokenError:
                msg = "非法token"
    
            if not result:
                return Response({"code": 1002, "msg": msg})
    
            return Response("订单列表")
    

    版本三:

    使用restful的认证组件认证

    class PrLoginView(APIView):
        authentication_classes = []
    
        def post(self, request, *args, **kwargs):
            username = request.data.get("username")
            passwork = request.data.get("password")
            user_obj = models.UserInfo.objects.filter(username=username, password=passwork).first()
            if not user_obj:
                return Response({"code": 1000, 'error': '用户名或密码错误'})
            payload = {
                "id": user_obj.pk,
                "name": user_obj.username,
            }
            token = get_token(payload, 5)
            return Response({"code": 1001, 'data': token})
    
    
    class PrOrderView(APIView):
    
        # authentication_classes = [JwtQuertParamsAuthentication]
    
        def get(self, request, *args, **kwargs):
    
            return Response("订单列表")
    
    # get_token函数
    import jwt
    import datetime
    from django.conf import settings
    def get_token(payload, timeout):
        salt = settings.SECRET_KEY
        headers = {
            "typ": "jwt_",
            "alg": "HS256",
        }
        payload["exp"] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout)
        token = jwt.encode(payload=payload, key=salt, headers=headers).decode("utf-8")
        return token
    

    实现一个restframework的认证类,将它应用到视图函数之中就可以了

    import jwt
    from jwt import exceptions
    from rest_framework.authentication import BaseAuthentication
    from django.conf import settings
    from rest_framework.exceptions import AuthenticationFailed
    class JwtQuertParamsAuthentication(BaseAuthentication):
        def authenticate(self, request):
            token = request.query_params.get("token")
            salt = settings.SECRET_KEY
            try:
                result = jwt.decode(token, salt, True)
            except exceptions.ExpiredSignatureError:
                msg = "token失效"
                raise AuthenticationFailed({"code": 1001, "msg": msg})
            except exceptions.DecodeError:
                msg = "token认证失败"
                raise AuthenticationFailed({"code": 1002, "msg": msg})
    
            except exceptions.InvalidTokenError:
                msg = "非法token"
                raise AuthenticationFailed({"code": 1003, "msg": msg})
    
            return (result, token)
    
            # 三种操作
            # 1.抛出错误,后续不再执行
            # 2.return一个元组,(1,2)认证通过,在视图中如果调用request.user 就是第一个值request.auth就是第二个
            # 3.None不做任何操作
    
  • 相关阅读:
    241. Different Ways to Add Parentheses java solutions
    89. Gray Code java solutions
    367. Valid Perfect Square java solutions
    46. Permutations java solutions
    116. Populating Next Right Pointers in Each Node java solutions
    153. Find Minimum in Rotated Sorted Array java solutions
    判断两颗树是否相同
    求二叉树叶子节点的个数
    求二叉树第k层的结点个数
    将二叉排序树转换成排序的双向链表
  • 原文地址:https://www.cnblogs.com/liuzhanghao/p/12686301.html
Copyright © 2011-2022 走看看