一、什么是JWT
JWT(JSON Web Tokens)是一种用于在网络应用环境间安全地传输信息的简洁的、URL安全的令牌标准。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
通俗地说,JWT的本质就是一个字符串,它是将用户信息保存到一个Json字符串中,然后进行编码后得到一个JWT token,并且这个JWT token带有签名信息,接收后可以校验是否被篡改,所以可以用于在各方之间安全地将信息作为Json对象传输。官网地址:https://jwt.io/
二、JWT的组成
1. Header
头部
是一个描述JWT元数据的JSON对象,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存,如下:
{
"alg": "HS256",
"typ": "JWT"
}
2. Payload
负载
是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择,如下:
iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT
除以上默认字段外,我们还可以自定义私有字段,一般会把包含用户信息的数据放到payload中,如下:
{
"name": "John Doe",
"num": 1516239022
}
3. Signature
签名
的作用是保证JWT的未被篡改。签名的生成方式是将编码后的头部、编码后的负载、秘密通过指定的算法进行签名。签名的作用是保证JWT的发送者不能抵赖自己发送的消息,接收者能够验证消息的完整性。这里是将前2部分的密文拼接起来,对这2部分进行HS256加密,然后加盐,最后在对加密后的内容用Base64加密一次。
注意JWT每部分的作用,在服务端接收到客户端发送过来的JWT token之后:
header
和payload
可以直接利用base64解码出原文,从header
中获取哈希签名的算法,从payload
中获取有效数据。signature
由于使用了不可逆的加密算法,无法解码出原文,它的作用是校验token有没有被篡改。服务端获取header
中的加密算法之后,利用该算法加上secretKey对header
、payload
进行加密,比对加密后的数据和客户端发送过来的是否一致。注意secretKey只能保存在服务端,而且对于不同的加密算法其含义有所不同,一般对于MD5类型的摘要加密算法,secretKey实际上代表的是盐值。
三、爬虫中遇到的js代码
以下是我遇到的网站示例:
四、使用Python实现
import random
import time
import jwt
def get_t():
# 模拟 getConfig() 方法返回的配置
config = {"key": "这是Key"} # 替换为实际的密钥
key = config["key"]
# 转换密钥为字节
r = key.encode("utf-8")
# 随机字符串 (JTI)
o = str(int(int(time.time() * 1000) * random.random() * 10000))
# print(o)
# 当前时间戳 + 300 秒 (未来 5 分钟)
s = int(time.time() + 300)
# print(s)
# JWT payload 数据
payload = {
"a": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", # 模拟用户代理
"exp": s,
"jti": o,
}
# JWT header
headers = {"alg": "HS256", "typ": "JWT"}
# 生成 JWT
token = jwt.encode(payload, r, algorithm="HS256", headers=headers)
print(token)
# 解密的方法
print(jwt.decode(token, r, algorithms=["HS256"], headers=headers))
# 获取 JWT 的 payload 部分(Base64 编码的第二部分)
jwt_parts = token.split(".")
jwt_payload_last_part = jwt_parts[2] # 获取签名部分
# 拼接结果
final_token = f"{jwt_payload_last_part}.{o}{s}"
return final_token
# 调用函数
result = get_t()
print(result)
参考链接:JWT详解
参考链接:Python使用JWT