python自定义JWT类

python自定义JWT

jwt说明

json web token:用于跨域时代替cookies&session技术,解决http无状态问题,保持会话状态
存储位置为ctrl+shift+i下的存储-本地存储中

实现步骤: 三大组成
header: 明确了算法和token种类,格式为字典,{‘alg’:‘HS256’,‘typ’:‘JWT’},alg代表要使用的算法,typ表名该token的类别,最后需转成json串并用base64加密
payload: 格式为字典:分为公有声明和私有申明
公共声明:JWT提供了内置关键字用于描述常见的问题,用户可根据自己需求添加key,{‘exp’:xxx #token的过期时间,‘iss’:xxx}, #指明此token的签发者(中大厂)
私有申明:用户根据自己业务需求添加的字典
username uid等,e.g. {‘username’:'yutaiixn“},最后需转成json串并用base64加密
signature签名: 用自定义(公司)的key, 对base64后的header + ‘.’ + base64后的payload进行hmac(封装了加盐后进行hash算法加密的库)计算:HS256(自定义的key , base64后的header + ‘.’ + base64后的payload)

jwt结果格式: base(header) + b’.’ +base(payload) +b’.’ + base64(sign)

详细代码

import json
import base64
import copy
import hmac

class Jwt():
	def __init__(self):
		pass
		
	#自定义base64加密方法
	#信息转成base64通过querystring的形式在url上传递,'+'和'/'在url中不能出现,urlsafe_b64encode()作用同b64encode(),会将+替换成-,/替换成_
	#base64加密时会自动将空的部分用‘=’代替,传递时将‘=’省略(replace()),传回时decode的时候再加上
	@staticmethod
	def b64encode(j_s):
		return base64.urlsafe_b64encode(j_s).replace(b'=',b'')

	#自定义base64解密方法
	def b64decode(b_s):
		#补全签发时替换掉的等号,找规律:肯定能被4整除,替换掉的‘=’个数是:4 - 总长 % 4
		rem  = len(b_s) % 4
		if rem > 0:
			b_s += b'=' * (4-rem)
		return base64.urlsafe_b64decode(b_s)
		
	@staticmethod
	def encode(payload,key,exp=300):	#假设payload传过来的就是个字典, {'username':'Terry'} 
		
		#header
		header = {'typ': 'JWT', 'alg': 'HS256'}
		#将header转换成json串,由于字典是无序的,需要用sort_keys保证最后字符串的输出顺序是有序的。
		#并用seperator保证json串比较瘦,多余的空格一律不要,seperator第一个''为键值对间分隔符,第二个''为key和值间分隔符
		header_json = json.dumps(header,sort_keys=True,seperator=(',',':'))
		#用base64加密,json串是字符串,base64的参数需要是字节串
		header_bs = Jwt.b64encode(header_json.encode())
		
		#payload
		#将用户传递来的参数payload深拷贝出来一份,不污染原先的参数payload
		my_payload = copy.deepcopy(payload)
		#添加token过期时间
		my_payload['exp'] = time.time() + int(exp)
		#生成json串
		payload_json = json.dumps(my_payload,sort_keys=True,separators=(',',':'))
		#用base64加密
		payload_bs =  Jwt.b64encode(payload_json.encode())

		#sign
		#key和payload一样是用户传进来,并确定用户传进来的key是字符串
		if isinstance(key,str):
			key = key.encode()
		#用自定义的key(该key保证了jwt非常可靠), 对base64后的header + '.' + base64后的payload进行hmac计算
		hm = hmac.new(key,header_bs + b'.' + payload_bs,digestmod='SHA256')
		#将sign用base64加密,需先根据需求转为二进制(digest())或十六进制(hexdigest())
		hm_bs =  Jwt.b64encode(hm.digest())

		#Jwt结果格式:base(header) + '.' +base(payload) +'.' + base64(sign)
		return header_bs + b'.' + payload_bs +b'.' + hm_bs

		@staticmethod
		def decode(jwt_s,key):
			#校验token
			#1.检查签名:签名是用前两项拼出来的【取出前两项base64串(结果中每一项有'.'隔开),再做一次hmac签名,与第三部分进行比较,若两者相等,校验成功,失败raise】
			#2. 检查时间戳是否过期【过期raise】
			#3.return payload明文,即payload字典对象
			header_bs,payload_bs,sign_bs = jwt_s.split(b'.')
			if isinstance(key,str):
				key = key.encode()
			hm = hmac.new(key,header_bs + b'.' + payload_bs,digestmod='SHA256')
			new_sign_bs = Jwt.b64encode(hm.digest())
			if new_sign_bs != sign_bs:
				raise
			#检查payload中的时间
			payload_json = Jwt.b64decode(payload_bs)
			#json字符串 -> python对象
			payload = json.loads(payload_json)
			exp = payload['exp']
			now_t = time.time()
			if now_t > exp:
				#过期
				raise
			return payload

	
	if __name__ == '__main__':
		#生成门票
		s = Jwt.encode({'username':'Terry'},'123456',100)
		#将门票加个key,做校验,然后打印出结果
		d = Jwt.decode(s,'123456')	#结果格式{'exp':xxx,'username':'Terry'}
		print(s)
		print(d)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值