JSON WEB Token——在两个组织之间传递安全可靠的消息。
JWT的两种实现:
JSON Web Signature(JWS)——一个有着简单统一表达方式的字符串。(签名)
-
base64enc{“alg”:指定签名加密算法,
“typ”:“JWT”}——>base64加密后得到的字符串Header -
base64enc {“iss”: 该JWT的签发者,
“sub”: 该JWT所面向的用户
“aud”:该JWT的接收方
“exp”:过期时间,是一个Unix时间戳(expires)
“iat”:什么时候签发
…
}——base64加密后的字符串PayLoad -
header.payload.secret——进行header中申明的加密方式。——signature。
-
jwt = Header.payload.signature
签名:jwt = Header.payload.signature
验签:1. jwt2 = Header.payload.signature是否等于jwt. 2. 再检验exp是否过期。
JSON Web Encryption(JWE)——相对于jws,jwe能同时保证安全性与完整性。(加密)
生成步骤:
- JOSE含义与JWS头部相同。
- 生成一个随机的Content Encryption Key (CEK)。
- 使用RSAES-OAEP 加密算法,用公钥加密CEK,生成JWE Encrypted Key。
- 生成JWE初始化向量。
- 使用AES GCM加密算法对明文部分进行加密生成密文Ciphertext,算法会随之生成一个128位的认证标记Authentication Tag。 6.对五个部分分别进行base64编码。
JWE的计算过程相对繁琐,不够轻量级,因此适合与数据传输而非token认证,但该协议也足够安全可靠,用简短字符串描述了传输内容,兼顾数据的安全性与完整性。
对比:
jws:使用时对照签名是否一致。对内容进行base64转码——反转码便可获取内容。
载荷部分一定不能包含敏感数据。
jwe:使用时需要解密不知道密钥根本就解不出来——它就是一个密文。payload数据采用加密方式进行加密。收到方不是进行验签而是解密。
以上内容参考来源:https://www.jianshu.com/p/50ade6f2e4fd
JWT的Python库
- itsdangerous
JSONWebSignatureSerializer(JWS)
TimedJSONWebSignatureSerializer (可设置有效期)
- pyjwt——允许完全定制payload内容和头
使用
>>> import jwt
>>> encoded_jwt = jwt.encode({
'some': 'payload'}, 'secret', algorithm='HS256')
>>> encoded_jwt
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg'
>>> jwt.decode(encoded_jwt, 'secret', algorithms=['HS256'])
{
'some': 'payload'}
编码:jwt.encode(载荷,‘secret’,algorithm=‘HS256’)
解码:jwt.decode(编码字符串,‘密钥’,algorithms=[‘加密方式’])
{}
项目中的封装:
import jwt
from flask import current_app
payload = {
...}
# 封装一个生成JWT的函数
def generate_iwt(payload,expiry,secret=None)
"""
生成jwt
:param payload: dict 载荷
:param expiry: datetime 有效期
:param secret: 密钥
:return: jwt
"""
_payload = {
'exp': expiry}
_payload.update(payload)
if not secret:
secrete = current_app.config['JWT_SECRET']
token = jwt.encode(_payload,secret.algorithm='HS256')
return token.decode()
# 校验jwt
def verify_jwt(token, secret=None):
"""
检验jwt
:param token: jwt
:param secret: 密钥
:return: dict: payload
"""
if not secret:
secret = current_app.config