标签:start datetime adt Fix 方法 序列化 ret timestamp 方案
JWT 简介JWT(Json WEB Token)是一种采用 Json 方式安装传输信息的方式。 JWT 有针对各种开发语言的库。 python 中使用的是 PyJWT,它是 Python 对 JWT 的实现。
JWT 应用场景服务端往往需要一个 ID 来表示客户端的身份,可以使用 session ,也可以在服务端创建一个 ID 返回给客户端。但是,要保证客户端不可篡改。JWT 就可以实现这种需求。
JWT 是在服务端生成一个标识,并使用某种算法对标识签名。CPU 计算资源,无法让浏览器自己主动检查过期的数据以清除。这种方案的优点是,不需要在服务端存放大量的session,减少了对内存的压力。
用于认证
常应用于服务端认证接口的 无
session方案 ,这是Jwt最常用的场景,一旦用户登录成功,就会得到Jwt,然后请求中就可以带上这个Jwt。服务器中Jwt验证通过,就可以被允许访问资源。甚至可以在不同域名中传递,在单点登录(Single Sign On)中应用广泛。
用于数据交换
Jwt可以防止数据被篡改,它还可以使用公钥、私钥,确保请求的发送者是可信的
JWT 安装pip install pyjwt
JWT 原理可知 jwt 生成的 token 分为三部分
json 序列化base64 编码后 使用点号连接后,加密算法使用 key 计算好一个结果,再被 base64 编码,得到签名所有数据都是明文传输的,只是做了 base64,如果是敏感信息,请不要使用
jwt。
数据签名的目的不是为了隐藏数据,而是保证数据不被篡改。如果数据篡改了,发回到服务器端,服务器使
用自己的 key 再计算一遍,然后进行签名比对,一定对不上签名。
Base64URL
Header 和 Payload 串型化的算法是 Base64URL。这个算法跟 Base64 算法基本类似,但有一些小的不同。JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符 +、/ 和 =,在 URL 里面有特殊含义,所以要被替换掉:= 被省略、+ 替换成 -,/ 替换成 ***_*** 。这就是 Base64URL 算法。JWT 使用JWT 方法说明| 方法 | 说明 |
|---|---|
jwt.encode(payload, key, algorithm=‘HS256‘, headers=None, json_encoder=None) |
生成 jwt, bytes 类型的 base64 编码 |
jwt.decode(jwt, key=‘‘, verify=True, algorithms=None, options=None, **kwargs) |
解码 jwt 为 bytes 类型的 json |
jwt.get_unverified_header(jwt) |
返回一个未验证的 jwt 头部信息 |
jwt.encode 参数说明
def encode(self,
payload, # type: Union[Dict, bytes]
key, # type: str
algorithm='HS256', # type: str
headers=None, # type: Optional[Dict]
json_encoder=None # type: Optional[Callable]
):
jwt.decode 参数说明
def decode(self,
jwt, # type: str
key='', # type: str
verify=True, # type: bool
algorithms=None, # type: List[str]
options=None, # type: Dict
**kwargs):
jwt.get_unverified_header() 参数说明
def get_unverified_header(self, jwt):
"""Returns back the JWT header parameters as a dict()
Note: The signature is not verified so the header parameters
should not be fully trusted until signature verification is complete
"""
headers = self._load(jwt)[2]
self._validate_headers(headers)
return headers
jwt.encode() 方法使用import jwt
password = '123456'
# 生成bytes类型的token
token = jwt.encode({"payload":'this is my payload'}, password, 'HS256')
print(' token:',token)
head, payload, signature = token.split(b'.') # 将成成的token(是bytes类型)切割成三段: head, payload, signature
print(' head:',head)
print(' payload:',payload)
print('signature:',signature)
------------------------------结果--------------------------------------
token: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXlsb2FkIjoidGhpcyBpcyBteSBwYXlsb2FkIn0.bPGtksZQ-ncY5mya0bF7EmpO82nlN1ohk9L2Dl2D4RA'
head: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9'
payload: b'eyJwYXlsb2FkIjoidGhpcyBpcyBteSBwYXlsb2FkIn0'
signature: b'bPGtksZQ-ncY5mya0bF7EmpO82nlN1ohk9L2Dl2D4RA'
jwt.decode() 方法使用import jwt
import base64
password = '123456'
# 生成bytes类型的token
token = jwt.encode({"payload":'this is my payload'}, password, 'HS256')
# 此函数是为了避免转码时候 base64 编码结尾处缺少 b'=',而报错.
def addpad(x):
suffix = 4 - len(x) % 4
return x + b'=' * suffix
head, payload, signature = token.split(b'.') # 将成成的token(是bytes类型)切割成三段: head, payload, signature
# 将 token (bytes 类型)转换为原来的类型
token_decode = jwt.decode(token, password, algorithms=['HS256'])
head_decode = base64.urlsafe_b64decode(addpad(head))
payload_decode = base64.urlsafe_b64decode(addpad(payload))
signature_decode = base64.urlsafe_b64decode(addpad(signature))
print(' token_decode:',token_decode, type(token_decode))
print(' head_decode:',head_decode, type(head_decode))
print(' payload_decode:',payload_decode, type(payload_decode))
print('signature_decode:',signature_decode, type(signature_decode))
------------------------------结果--------------------------------------
token_decode: {'payload': 'this is my payload'} <class 'dict'>
head_decode: b'{"typ":"JWT","alg":"HS256"}' <class 'bytes'>
payload_decode: b'{"payload":"this is my payload"}' <class 'bytes'>
signature_decode: b'l\xf1\xad\x92\xc6P\xfaw\x18\xe6l\x9a\xd1\xb1{\x12jN\xf3i\xe57Z!\x93\xd2\xf6\x0e]\x83\xe1\x10' <class 'bytes'>
jwt.decode() 方法实现过期验证import jwt
import datetime
import threading
event = threading.Event()
passwd = '123456'
token = jwt.encode({
'a':'test',
'exp': int(datetime.datetime.now().timestamp() + 5)
}, passwd, 'HS256')
print(token)
print('===============================')
print('start at about: ',int(datetime.datetime.now().timestamp()))
while True:
if not event.wait(1):
try:
print(jwt.decode(token, passwd))
except Exception as e:
print(e)
break
执行结果
b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhIjoidGVzdCIsImV4cCI6MTU1MzQ0MDc5OH0.jzwOxmsp3zqVTXi38hsmu8K7c47j4NV8nPxQe9cQ3E0'
===============================
start at about: 1553440793
{'a': 'test', 'exp': 1553440798}
{'a': 'test', 'exp': 1553440798}
{'a': 'test', 'exp': 1553440798}
{'a': 'test', 'exp': 1553440798}
{'a': 'test', 'exp': 1553440798}
Signature has expired
jwt.get_unverified_header(jwt) 方法使用import jwt
password = '123456'
token = jwt.encode({"payload":'this is my payload'}, password, 'HS256')
print(' token:',token)
print('jwt_header:',jwt.get_unverified_header(token))
------------------------------结果--------------------------------------
token: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXlsb2FkIjoidGhpcyBpcyBteSBwYXlsb2FkIn0.bPGtksZQ-ncY5mya0bF7EmpO82nlN1ohk9L2Dl2D4RA'
jwt_header: {'typ': 'JWT', 'alg': 'HS256'}标签:start datetime adt Fix 方法 序列化 ret timestamp 方案
原文地址:https://www.cnblogs.com/shichangming/p/10591312.html