zoukankan      html  css  js  c++  java
  • 解析jwt实现原理

    熟悉drf框架:https://www.cnblogs.com/wupeiqi 武沛奇

    哔哩哔哩视频教学笔记:

    1.jwt(登录注册)

    json web token,一般用于用户认证(前后端分离、微信小程序/APP开发) 其他直接用cookies/session即可

    token的校验过程:

    前端——携带token进行认证——后端———返回携带的token进行校验

    基于传统的token认证:

    # 用户登录,服务段返回token,并将token保存在服务器,以后用户再来访问时,需要携带token,服务端获取token后再去数据库中获取token进行校验。

    jwt:

    # 用户登录,服务端给用户返回一个token(服务器不保存),
    以后用户再来访问,需要携带token,服务器获取token后,再做token的校验,
    优势:相较于传统的token相比,它无需在服务器端保存token。

    2.jwt实现过程

    *第一步瀛湖提交用户和密码给服务端。如果登录成功,使用创建一个token,并给用户返回。

    官网:

     

    注意:jwt生成的token由三段字符串组成,并用.连接起来的。

    *第一段字符串,HEADER,内部包括算法/token类型,

    json转换成字符串,然后做base64url加密(base64加密:+_).

    {
        "alg":"HS256",
        "typ":"JWT"
    }

    *第二段字符串,payload自定义值。

    json转换成字符串,然后做base64url加密(base64加密:+_).

    {
        "id":"123123",
        "name":"Eric",
        "exp":"124521589" # 超时时间
    }
    • 第三段字符串:

    • ''''
      第一步:第1、2部分密文件拼接起来
      第二步:对前2部分密文进行HS256加密 + 加盐
      第三步:对HS256加密后的密文再做base64url加密
      
      ''''
    • 以后用户再来访问时候,需要携带token,后端需要对token进行校验

    • 获取token:

    • 第一步:对token进行切割

    • 第二部:对第二段进行base64url解密,并获取payload信息,检测token是否已经超时

      {
          "id":"123123",
          "name":"Eric",
          "exp":"124521589" # 超时时间
      }
    • 
      
    • 第三步:把第1,2段拼接起来,再次执行sah256加密

    • image-20200322142247716

    3.应用

     # pip install pyjwt

    使用:刨析内部源码

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

    4.扩展

    # pip3 install djangoresframework-jwt

    djangorestframework-jwt本质是调用pyjwt实现。

     

    django案例

    from django.http import JsonResponse
    from django.views import View
    from django.views.decorators.csrf import csrf_exempt
    from django.utils.decorators import method_decorator
    
    from utils.jwt_auth import create_token
    
    
    @method_decorator(csrf_exempt, name='dispatch')
    class LoginView(View):
        def post(self, request, *args, **kwargs):
            """ 用户登录 """
            user = request.POST.get('username')
            pwd = request.POST.get('password')
    
            # 检测用户和密码是否正确,此处可以在数据进行校验。
            if user == 'wupeiqi' and pwd == '123':
                # 用户名和密码正确,给用户生成token并返回
                token = create_token({'username': 'wupeiqi'})
                return JsonResponse({'status': True, 'token': token})
            return JsonResponse({'status': False, 'error': '用户名或密码错误'})
    
    
    @method_decorator(csrf_exempt, name='dispatch')
    class OrderView(View):
    
        def get(self, request, *args, **kwargs):
            print(request.user_info)
            return JsonResponse({'data': '订单列表'})
    
        def post(self, request, *args, **kwargs):
            print(request.user_info)
            return JsonResponse({'data': '添加订单'})
    
        def put(self, request, *args, **kwargs):
            print(request.user_info)
            return JsonResponse({'data': '修改订单'})
    
        def delete(self, request, *args, **kwargs):
            print(request.user_info)
            return JsonResponse({'data': '删除订单'})

    drf_jwr_demo

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import jwt
    import datetime
    from jwt import exceptions
    
    JWT_SALT = 'iv%x6xo7l7_u9bf_u!9#g#m*)*=ej@bek5)(@u3kh*72+unjv='
    
    
    def create_token(payload, timeout=20):
        """
        :param payload:  例如:{'user_id':1,'username':'wupeiqi'}用户信息
        :param timeout: token的过期时间,默认20分钟
        :return:
        """
        headers = {
            'typ': 'jwt',
            'alg': 'HS256'
        }
        payload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout)
        result = jwt.encode(payload=payload, key=JWT_SALT, algorithm="HS256", headers=headers).decode('utf-8')
        return result
    
    
    def parse_payload(token):
        """
        对token进行和发行校验并获取payload
        :param token:
        :return:
        """
        result = {'status': False, 'data': None, 'error': None}
        try:
            verified_payload = jwt.decode(token, JWT_SALT, True)
            result['status'] = True
            result['data'] = verified_payload
        except exceptions.ExpiredSignatureError:
            result['error'] = 'token已失效'
        except jwt.DecodeError:
            result['error'] = 'token认证失败'
        except jwt.InvalidTokenError:
            result['error'] = '非法的token'
        return result

    view.py

    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    from utils.jwt_auth import create_token
    from extensions.auth import JwtQueryParamAuthentication, JwtAuthorizationAuthentication
    
    
    class LoginView(APIView):
        def post(self, request, *args, **kwargs):
            """ 用户登录 """
            user = request.POST.get('username')
            pwd = request.POST.get('password')
    
            # 检测用户和密码是否正确,此处可以在数据进行校验。
            if user == 'wupeiqi' and pwd == '123':
                # 用户名和密码正确,给用户生成token并返回
                token = create_token({'username': 'wupeiqi'})
                return Response({'status': True, 'token': token})
            return Response({'status': False, 'error': '用户名或密码错误'})
    
    
    class OrderView(APIView):
        # 通过url传递token
        authentication_classes = [JwtQueryParamAuthentication, ]
    
        # 通过Authorization请求头传递token
        # authentication_classes = [JwtAuthorizationAuthentication, ]
    
        def get(self, request, *args, **kwargs):
            print(request.user, request.auth)
            return Response({'data': '订单列表'})
    
        def post(self, request, *args, **kwargs):
            print(request.user, request.auth)
            return Response({'data': '添加订单'})
    
        def put(self, request, *args, **kwargs):
            print(request.user, request.auth)
            return Response({'data': '修改订单'})
    
        def delete(self, request, *args, **kwargs):
            print(request.user, request.auth)
            return Response({'data': '删除订单'})

     

     

     

  • 相关阅读:
    Serialization and deserialization are bottlenecks in parallel and distributed computing, especially in machine learning applications with large objects and large quantities of data.
    Introduction to the Standard Directory Layout
    import 原理 及 导入 自定义、第三方 包
    403 'Forbidden'
    https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
    These interactions can be expressed as complicated, large scale graphs. Mining data requires a distributed data processing engine
    mysqldump --flush-logs
    mysql dump 参数
    mysql dump 参数
    如果是在有master上开启了该参数,记得在slave端也要开启这个参数(salve需要stop后再重新start),否则在master上创建函数会导致replaction中断。
  • 原文地址:https://www.cnblogs.com/Gaimo/p/12546259.html
Copyright © 2011-2022 走看看