JWT令牌产生原理

import base64
import copy
import json
import hmac
import time

class Jwt():
    def __init__(self):
        pass
#  生成令牌
    @staticmethod
    def encode(payload,key,exp=100):
        #创建header
        header = {'alg':'HS256','typ':'JWT'}
        # 创建Header json str
        # separators 第一个参数表示 json串中每一个键值对之间用什么相连, 第二个参数表示key和value用什么相连
        # sort_keys表示 json串按key排序输出
        header_j = json.dumps(header,separators=(',',':'),sort_keys=True)
        header_bs = Jwt.b64encode(header_j.encode())

        # 创建payload 部分
        payload = copy.deepcopy(payload)
        #payload['exp'] = int(time.time()+exp)
        payload['exp'] = int(exp)

        # 生成payload 的json串
        payload_j = json.dumps(payload,separators=(',',':'),sort_keys=True)
        #base64
        payload_bs = Jwt.b64encode(payload_j.encode())


        # 生成sign

        to_sign_str = header_bs + b'.' + payload_bs

        # hmac new 中参数 需要用bytes
        if isinstance(key,str):
            # 判断key类型,为str 则转化为byte
            key = key.encode()
        hmac_obj = hmac.new(key,to_sign_str,digestmod='SHA256')
        # 获取签名结果
        sign = hmac_obj.digest()
        # 生成sign 的base64
        sign_bs = Jwt.b64encode(sign)

        return header_bs + b'.' + payload_bs + b'.' + sign_bs

    @staticmethod
    def b64encode(s):
        # 替换原生base64中的=
        return base64.urlsafe_b64encode(s).replace(b'=',b'=')

    @staticmethod
    def b64decode(bs):
        rem = len(bs) % 4
        bs += b'=' * (4-rem)
        return base64.urlsafe_b64decode(bs)


# 解析令牌
    @staticmethod
    def decode(token,key):
        header_bs,payload_bs,sign_bs = token.split(b'.')
        if isinstance(key,str):
            key = key.encode()
        # 重新计算签名
        hm = hmac.new(key,header_bs + b'.'+ payload_bs,digestmod='SHA256')
        new_sign = Jwt.b64encode(hm.digest())
        if sign_bs != new_sign:
            # 当前传过来的token违法
            raise JwtError('your token is valid')


        payload_j = Jwt.b64decode(payload_bs)
        payload = json.loads(payload_j)
        print(type(payload_j))
        exp = payload['exp']
        now = time.time()
        # 对比两个时间是否过期
        if exp<now:
            raise JwtError('Your token is expired')

        return payload
#  自定义异常
class JwtError(Exception):
    def __init__(self,error_msg):
        self.error = error_msg
    def __str__(self):
        return ''%(self.error)

if __name__ == '__main__':
    res = Jwt.encode({'u':'b'},'c')
    print(res)
    time.sleep(3)
    t = Jwt.decode(res,'abcde123')
    print(t)

你可能感兴趣的:(JWT令牌产生原理)