zoukankan      html  css  js  c++  java
  • 浅谈jwt在python中的使用

    • jwt概述

      1. 什么是jwt?

        json web token

      2. jwt应用场景?

        1. 微信小程序
        2. 移动设备
        3. 前后端分离项目
      3. 认证方式

        1. 传统认证

          用户登录成功后,服务端下发token,并保存在服务端(database/session/redis/file)中,当客户端再访问服务端需要携带token,服务端获取客户端传来的token后再去服务端(database/session/redis/file)中获取token进行时间和token校验,如果一样,则顺利访问,否则提示token不合法或者过期。
          
        2. jwt认证

          用户登录成功后,服务端下发token,此时服务端并不保存token,当客户端再访问服务端时,需要携带token,服务端获取客户端传来的token后,对此token通过某些算法进行分析来确认token是否合法。
          

      jwt实现过程

      1. 组成部分

        1. 头部(HEADER)

          {
            "alg": "HS256",
            "typ": "JWT"
          }
          
        2. 载荷(PAYLOAD)

          {
            "sub": "1234567890",
            "name": "John Doe",
            "exp": 1516239022
          }
          
        3. 签名(VERIFY SIGNATURE)

          HMACSHA256(
            base64UrlEncode(header) + "." +
            base64UrlEncode(payload),
          	SALT
          )
          
      2. 如何组成

        1. 将头部使用base64UrlEncode编码 得到StringA
        2. 将载荷使用base64UrlEncode编码 得到StringB
        3. 将第一步和第二步 使用.进行字符串拼接 得到StringA.StringB
        4. 设置盐值(SALT)
        5. 将第三步的字符串和盐值进行hash256加密(为了安全使用盐)得到hash256('StringA.StringB',SALT)
        6. 将第3步得到的字符串和第五步得到的hash256加密后的字符串用.进行拼接
      3. 最终生成结构

        eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
        
      • 辅助函数

        # 封装 base64UrlEncode方法
        def base64UrlEncode(data):
          '''
          	@params : dict
          	@return : string
          '''
          # 1. 判断参数是否为字典,如不是字典直接返回
          if type(data) is not dict:
            return json.dumps({"code":1001,"msg":"参数类型不合法"},ensure_ascii=False)
          # 2.将字典转成json串
          json_str = json.dumps(data)
          # 3.将json串转成字节
          bytes_str = json_str.encode('utf-8')
          # 4.base64编码
          b64_bytes = base64.b64encode(bytes_str)
          # 5.将字节类型转成字符串类型,并返回
          return b64_bytes.decode('utf-8')
        
        # 封装sha256方法
        import hashlib
        def sha256hex(raw,salt):
          '''
          @params: raw 原始字符串
          @params: salt 随机盐值
          @return : string
          '''
          new_str = raw+salt
          sha256 = hashlib.sha256()
          sha256.update(new_str.encode())
          return sha256.hexdigest()
        
      • 生成token

        # 代码块(生成token)
        from utils.helper import base64UrlEncode,sha256hex
        from rest_framework.views import APIView
        from rest_framework.response import Response
        from django.conf import settings
        class CreateTokenView(APIView):
            def post(self,request):
              # jwt头部
                header = {
                  "alg": "HS256",
                  "typ": "JWT"
                }
                # jwt载荷
                payload = {
                    "sub": "1234567890",
                    "name": "John Doe",
                    "exp": 1516239022
                }
                # 头部base64编码
                header_string = base64UrlEncode(header)
                # 载荷base64编码
                payload_string = base64UrlEncode(payload)
                # 盐值
                salt = settings.SECRET_KEY
        				# 生成签名
                sign = sha256hex(header_string+'.'+payload_string,salt)
                # 构造token
                token = header_string+"."+payload_string+"."+sign
                # 返回
                return Response({
                    "code":20000,
                    "data":{
                        "token":token
                    }
                })
        
        # 返回结果
        {
            "code": 20000,
            "data": {
                "token": "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogIkpvaG4gRG9lIiwgImV4cCI6IDE1MTYyMzkwMjJ9.c7364fb2a00fe6aa843fae23e179fe97dd820f26a47a769c621ff560945278c7"
            }
        }
        
      • 验证token

        # 代码块(生成token)
        from utils.helper import base64UrlEncode,sha256hex
        from rest_framework.views import APIView
        from rest_framework.response import Response
        from django.conf import settings
        class CheckTokenView(APIView):
            def post(self,request):
                # 获取http headers  token
                token = request.META.get("HTTP_TOKEN")
                # 将token分解三部分
                payload_b64_header = token.split('.')[0]
                payload_b64_payload = token.split('.')[1]
                payload_b64_sign = token.split('.')[2]
                # 将第二部分解析,获取过期时间
                json_str = base64_decode(payload_b64_payload)
                exp = json.loads(json_str)
                # 判断当前时间和过期时间
                if exp['exp'] < int(time.time()):
                    return Response({
                        "code":1003,
                        "msg":"token过期"
                    })
                # 从配置文件中读取盐值
                salt = settings.SECRET_KEY
                # 在有效期内,判断签名是否一致
                sign = sha256hex(payload_b64_header+'.'+payload_b64_payload,salt)
                if sign == payload_b64_sign:
                    return Response({
                        "code":1000,
                        "msg":"验证成功"
                    })
                return Response({
                    "code":"1002",
                    "msg":"验证失败"
                })    
        
  • 相关阅读:
    第三次作业
    第二次作业
    第一次作业—编译原理概述
    第六次课堂作业——正规文法与正规式
    词法分析程序的设计与实现
    1702第四次作业(文法和语文总结与梳理)
    1702第三次作业(语法树,短语,直接短语,句柄)
    软工1702第一次作业(简述编译程序)
    random库的使用
    基本的字符串之切片
  • 原文地址:https://www.cnblogs.com/wuxiaoshi/p/12310196.html
Copyright © 2011-2022 走看看