跳转至

Jose

python-jose 是一个用于在 Python 中处理 JSON Web Tokens (JWT)、JSON Web Signatures (JWS) 和 JSON Web Encryption (JWE) 的库,基于 JOSE (JSON Object Signing and Encryption) 标准。它通常用于对信息进行签名、加密,特别是在 OAuth2、OpenID Connect 和 API 认证中,广泛应用于用户身份验证和授权流程中。

以下是 python-jose 的详解教程,介绍如何生成、验证 JWT 以及常见的应用场景。

1. 安装 python-jose

首先需要安装 python-jose,可以通过 pip 来安装:

pip install python-jose

2. 基本概念

  • JWT (JSON Web Token): 一种开放的标准 (RFC 7519),定义了一种用于安全传输信息的紧凑、自包含的方式,通常用于认证和信息交换。
  • JWS (JSON Web Signature): 是 JWT 的一种使用形式,通过对 JWT 进行签名确保信息未被篡改。
  • JWE (JSON Web Encryption): 是 JWT 的另一种形式,用于对 JWT 进行加密,从而确保信息的机密性。

3. 使用 JWT 的基本流程

JWT 由三部分组成:头部 (header)、载荷 (payload) 和签名 (signature),它们被 . 分隔。下面是如何使用 python-jose 来生成和验证 JWT。

3.1 生成 JWT

python-jose 支持生成加密和签名的 JWT。在这里我们使用签名的 JWT (JWS) 作为示例。生成 JWT 的基本步骤如下:

from jose import jwt

# 定义密钥和算法
secret_key = 'mysecretkey'
algorithm = 'HS256'

# 定义 payload(有效载荷)
payload = {
    'sub': '1234567890',
    'name': 'John Doe',
    'admin': True
}

# 生成 JWT
token = jwt.encode(payload, secret_key, algorithm=algorithm)
print(f"Generated Token: {token}")

这里我们使用 HS256 签名算法和一个密钥 (secret_key) 来生成 JWT。生成的 token 可以用于客户端的认证请求中。

3.2 验证 JWT

一旦你有了 JWT,接下来就是验证它的真实性。这通常发生在服务器端,确保客户端发送的 JWT 未被篡改。

# 验证并解码 JWT
decoded_payload = jwt.decode(token, secret_key, algorithms=[algorithm])
print(f"Decoded Payload: {decoded_payload}")

jwt.decode() 函数会验证 JWT 的签名,如果签名有效,则返回原始的 payload。如果签名无效或密钥不匹配,它将抛出异常。

4. 过期时间和其他标准声明

JWT 可以包含一些标准声明(claims),例如 exp(过期时间)、iat(签发时间)、sub(主题)等。你可以在 payload 中添加这些声明来控制 JWT 的有效期。

4.1 设置过期时间

import datetime
from jose import jwt

# 定义密钥和算法
secret_key = 'mysecretkey'
algorithm = 'HS256'

# 设置过期时间(10分钟后过期)
expiration = datetime.datetime.utcnow() + datetime.timedelta(minutes=10)

# 定义 payload,并加入 exp 声明
payload = {
    'sub': '1234567890',
    'name': 'John Doe',
    'exp': expiration
}

# 生成 JWT
token = jwt.encode(payload, secret_key, algorithm=algorithm)
print(f"Generated Token with Expiration: {token}")

# 解码并验证 JWT
try:
    decoded_payload = jwt.decode(token, secret_key, algorithms=[algorithm])
    print(f"Decoded Payload: {decoded_payload}")
except jwt.ExpiredSignatureError:
    print("Token has expired")

通过添加 exp 字段,我们可以为 JWT 设置一个过期时间。过期后,jwt.decode() 将会抛出 ExpiredSignatureError 异常。

4.2 其他声明

你还可以添加其他声明,如 iss(发行者)、aud(接收者)等。例如:

payload = {
    'sub': '1234567890',
    'name': 'John Doe',
    'iss': 'mycompany',
    'aud': 'myaudience',
    'exp': expiration
}

在解码时,使用 jwt.decode() 函数可以验证 issaud,确保 JWT 是由正确的发行者发出并被正确的接收者使用。

# 验证 JWT,包括发行者和接收者
decoded_payload = jwt.decode(token, secret_key, algorithms=[algorithm], issuer='mycompany', audience='myaudience')

5. 使用非对称加密 (RSA)

除了 HMAC 算法 (HS256),python-jose 还支持 RSA 算法 (RS256)。在使用 RSA 时,需要生成一对公钥和私钥,私钥用于签名,公钥用于验证。

5.1 生成 RSA 密钥对

你可以使用 OpenSSL 或其他工具生成 RSA 公钥和私钥对。

# 生成私钥
openssl genrsa -out private_key.pem 2048

# 生成公钥
openssl rsa -in private_key.pem -outform PEM -pubout -out public_key.pem

5.2 使用 RSA 签名和验证

使用 RSA 时,签名和验证的过程与 HMAC 类似。

from jose import jwt

# 加载私钥和公钥
with open('private_key.pem', 'r') as f:
    private_key = f.read()

with open('public_key.pem', 'r') as f:
    public_key = f.read()

# 定义 payload
payload = {
    'sub': '1234567890',
    'name': 'John Doe'
}

# 使用私钥生成 JWT
token = jwt.encode(payload, private_key, algorithm='RS256')
print(f"Generated Token: {token}")

# 使用公钥验证 JWT
decoded_payload = jwt.decode(token, public_key, algorithms=['RS256'])
print(f"Decoded Payload: {decoded_payload}")

6. 常见应用场景

6.1 用户认证

JWT 常用于用户认证。用户登录时,服务器生成一个 JWT 并发送给客户端,客户端随后将 JWT 包含在请求头中发给服务器,服务器验证 JWT 以确认用户身份。

6.2 API 授权

在 API 访问时,JWT 可用于授权。客户端使用 JWT 访问受保护的资源,服务器通过验证 JWT 确定请求是否有权限。

7. 总结

python-jose 是一个功能强大的库,适用于生成和验证 JWT。通过本文的教程,你学会了如何生成、验证 JWT,并且了解了如何使用对称和非对称加密算法来处理 JWT。你可以根据自己的需求选择合适的算法和声明,来确保认证和授权过程中的安全性。