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不做任何操作
    
  • 相关阅读:
    ORACLE增删改查以及case when的基本用法
    ORACLE自增函数,一般函数
    Charles下载与破解方法
    ORACLE常见问题收集
    SpringBoot项目 org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Jetty servlet container报错
    Cordova搭建环境与问题小结
    redis集群搭建
    centos下的redis一键安装shell脚本
    爬虫那些事儿
    Scrapy爬虫框架基本使用
  • 原文地址:https://www.cnblogs.com/liuzhanghao/p/12686301.html
Copyright © 2011-2022 走看看