JWT---自我实现

什么是: json-web-token

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。

一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。

为什么使用JWT?

1.jwt本质上也是为了解决http无状态。
2.随着技术的发展,分布式web应用的普及,通过session管理用户登录状态成本越来越高,因此慢慢发展成为token的方式做登录身份校验,然后通过token去取redis中的缓存的用户信息,随着之后jwt的出现,校验方式更加简单便捷化,无需通过redis缓存,而是直接根据token取出保存的用户信息,以及对token可用性校验,单点登录更为简单。
3.某些特定情况下我们无法使用cookie和session存储数据,例如(安卓客户端和ios客户端),这时候就需要使用jwt-token。

头部(Header)

头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象。

{“typ”:“JWT”,“alg”:“HS256”}

在头部指明了签名算法是HS256算法。 我们进行Base64编码,编码后的字符串如下:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

载荷(playload)

​载荷就是存放有效信息的地方,格式为字典-此部分分为公有声明和私有声明

  公共声明:JWT提供了内置关键字用于描述常见的问题

此部分均为可选项,用户根据自己需求 按需添加key,常见公共声明如下:

{'exp':xxx, # Expiration Time 此token的过期时间的时间戳
 'iss':xxx,# (Issuer) Claim 指明此token的签发者
 'aud':xxx, #(Audience) Claim 指明此token的签发面向群体
 'iat':xxx, # (Issued At) Claim 指明此创建时间的时间戳
}
	私有声明:用户可根据自己业务需求,添加自定义的key,例如如下:
{'username': 'caoxudong'}
	公共声明和私有声明均在同一个字典中;转成json串并用base64加密

签证(signature)

jwt的第三部分是一个签证信息,这个签证信息由三部分组成:
​ 签名规则如下:

​ 根据header中的alg确定 具体算法,以下用 HS256为例

​ HS256(自定义的key , base64后的header + ‘.’ + base64后的payload)

​ 解释:用自定义的key, 对base64后的header + ‘.’ + base64后的payload进行hmac计算

jwt结果格式

base64(header) + ‘.’ + base64(payload) + ‘.’ + base64(sign)

'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzUyNzkxODkuNzAxMTg2LCJ1c2VybmFtZSI6ImNhb3h1ZG9uZyJ9.EPLbvcOFuvxC2JoFEoAdEW7uMx2UGfnOdPsLAikqAgo'

自定义jwt

import time
import base64
import hmac
import json
import copy

class Jwt():

    def __init__(self):
        pass

    @staticmethod
    def encode(payload,key,exp=300):
        '''
        :param payload: 荷载内容
        :param key: 自己的钥匙(加盐)
        :param exp: 过期时间
        :return: 生成的token
        '''
        header = {'alg':'HS256','typ':'JWT'}
        # 将字典转为json串
        header_json = json.dumps(header,sort_keys=True,separators=(',',':'))
        # 将json串进行base64加密
        str_header = Jwt.b64_encode(header_json.encode())

        exp = time.time() + exp
        payload = copy.deepcopy(payload)
        payload['exp'] = exp
        payload = json.dumps(payload,sort_keys=True,separators=(',',':'))
        str_payload = Jwt.b64_encode(payload.encode())

        str_b64 = str_header + b'.' + str_payload
        hm_sign = hmac.new(key.encode(),str_b64,digestmod='SHA256')
        str_sign = Jwt.b64_encode(hm_sign.digest())
        return str_header+b'.'+str_payload+b'.'+str_sign


    @staticmethod
    def b64_encode(j_s):
	    #将 '+'替换成 '-',将'/'替换成'_',并且将多余的'='去掉
        return base64.urlsafe_b64encode(j_s).replace(b'=',b'')

    @staticmethod
    def b64_decode(b_s):
    	# 将缺少的'='补全
        rem = len(b_s) % 4
        if rem > 0:
            b_s += b'=' * (4-rem)
        return base64.urlsafe_b64decode(b_s)

    @staticmethod
    def decode(token,key):
        header_bs,payload_bs,sign = token.split(b'.')
        hm = hmac.new(key.encode(),header_bs+b'.'+payload_bs,digestmod='SHA256')
        if sign != Jwt.b64_encode(hm.digest()):
            raise ('校验失败')

        payload_js = Jwt.b64_decode(payload_bs)
        payload = json.loads(payload_js)
        if payload['exp'] < time.time():
            raise ('时间已过期')
        return payload


    def run(self):
        payload = {'username':'caoxudong'}
        key = 'cxd'
        # 生成token
        token = self.encode(payload,key)
        print(token)
        # 验证通过后返回字典内容
        value = self.decode(token, key)
        print(value)

if __name__ == '__main__':
    s = Jwt()
    s.run()

输出结果:

b'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzUyOTE5NTYuMzI2Mjg1NCwidXNlcm5hbWUiOiJjYW94dWRvbmcifQ.wimiGX6MbBHwGAm0oZWyjksUNOBbEjyhdhCuy_S1-ls'

{'exp': 1575291956.3262854, 'username': 'caoxudong'}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值