JSON Web Token 包含用点(".")分隔的三部分:
形如:
xxxxxxxxxx
xxxxx.yyyyy.zzzzz
Header 通常包含两部分:
下面是一个例子:
xxxxxxxxxx
{
"alg": "HS256",
"typ": "JWT"
}
使用 Base64Url 对 Header 进行编码,形成 JWT 的第一部分。
JWT 的第二部分是 Payload。它包含声明,声明是关于实体(实体通常是用户)和可选元数据的一系列语句。有三种类型的声明:预留的、公有的、私有的。
预留的声明: 预留的声明是一组预定义的声明。不强制,但是推荐使用它们。预留的声明(名称长度都是 3)包括:
iss(issuer)
:请求的发起人exp(expiration time)
:以秒为单位的过期时间sub (subject)
:主题aud (audience)
:参与者公有的声明: 使用公有的声明时应避免名称冲突
私有的声明: 私有的声明是自定义的声明,用于在系统的各部分间共享信息
下面是一个例子:
xxxxxxxxxx
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
使用 Base64Url 对 Payload 进行编码,形成 JWT 的第二部分。
签名部分使用编码后的 Header、编码后的 Payload、密钥以及** Header 中指定的算法**生成。
假如算法是 HMAC SHA256
,那么签名的计算方式是:
xxxxxxxxxx
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名用于核实 JWT 的发送者,确保消息没有被篡改。
JWT 包含三个用点分隔的 Base64 字符串。
下面是一个示例 JWT:
依赖包:
代码:
xxxxxxxxxx
import time
from typing import Tuple, Dict, Any
import jwt
import Crypto.PublicKey.RSA as RSA
def generate_rsa_keys(bits: int = 2048) -> Tuple[bytes, bytes]:
# 随机生成 RSA key
key: RSA.RsaKey = RSA.generate(bits)
# 编码后的私钥
private_pem: bytes = key.exportKey()
# 编码后的公钥
public_pem: bytes = key.publickey().exportKey()
return private_pem, public_pem
def client_side(payload: Dict[str, Any], private_key: bytes) -> str:
return jwt.encode(payload, private_key, "RS256")
def server_side(token: str, public_key: bytes) -> Dict[str, Any]:
return jwt.decode(token, public_key, "RS256")
def test() -> None:
private_key, public_key = generate_rsa_keys() # type: bytes, bytes
payload: Dict[str, Any] = {
"user_id": 1,
"exp": time.time() + 100
}
token: str = client_side(payload, private_key)
print(token)
decoded_payload: Dict[str, Any] = server_side(token, public_key)
print(decoded_payload)
if __name__ == "__main__":
test()
重放攻击(Replay Attacks)又称重播攻击、回放攻击或新鲜性攻击(Freshness Attacks),是指攻击者发送目的主机已接收过的包,来达到欺骗系统的目的,主要用于身份认证过程,破坏认证的正确性。
jti
是被放到 JWT 中的唯一 ID,可以防止重放攻击。