itsdangerous 是一个用于安全数据序列化和签名的库,主要用来确保数据在传输过程中不被篡改。它常用于生成安全令牌,以便在 Web 应用程序中实现安全的会话管理和数据交换,注意,它的目标是签名,而不是加密。下面我们将详细介绍 itsdangerous 的使用方法。
安全数据传输
有时你需要将一些数据发送到不受信任的环境,然后再取回这些数据。为了安全地做到这一点,数据必须进行签名,以检测是否有改动。通过一个只有你知道的密钥,你可以对数据进行加密签名,并将其交给其他人。当你取回数据时,可以确保数据没有被篡改。
接收者可以看到数据,但不能修改它,除非他们也拥有你的密钥。因此,只要你保持密钥不被泄漏和复杂性,数据的安全性就能得到保障。
安装
你可以通过 pip 安装并更新 itsdangerous
:
pip install -U itsdangerous
signer 数据签名基本使用示例
from itsdangerous import Signer, TimestampSigner
# 创建一个签名器
signer = Signer('secret-key')
# 签名数据
signed = signer.sign('my data')
print(signed) # 输出带签名的数据: b'my data.8DRtXYcvmlzEWlMaksLh3ugEnP4'
# 验证并提取原始数据
try:
original = signer.unsign(signed)
print(original) # 输出 b'my data'
except itsdangerous.BadSignature:
print('Invalid signature!')
# 带时间戳的签名器
timestamp_signer = TimestampSigner('secret-key')
# 签名数据
timestamped_signed = timestamp_signer.sign('my data')
print(timestamped_signed) # 输出 b'my data.ZrG36w.KqENCZXJvs6x1i-VBN4Ix3Trfpg'
# 验证并提取原始数据,带时间检查,验证数据并检查是否过期
try:
original = timestamp_signer.unsign(timestamped_signed, max_age=60) # max_age 以秒为单位
print(original) # 输出 b'my data'
except itsdangerous.SignatureExpired:
print('Signature expired!')
except itsdangerous.BadSignature:
print('Invalid signature!')
serializer 序列化基本使用示例
-
取消订阅链接: 假设你有一个订阅新闻简报的用户。你希望用户可以通过点击电子邮件中的链接来取消订阅,而不必登录账户。你可以在 URL 中签名用户的 ID,并将该 URL 发送给用户。
from itsdangerous import URLSafeSerializer serializer = URLSafeSerializer('secret-key') user_id = 12345 token = serializer.dumps(user_id) unsubscribe_url = f"https://example.com/unsubscribe/{token}" print(unsubscribe_url) # https://example.com/unsubscribe/MTIzNDU.xaB-LZfpSNP0fTCcz0aMqMfpoHA
用户点击链接后,你可以验证并提取用户的 ID:
token = '从URL中提取的token' try: user_id = serializer.loads(token) print(f"User ID: {user_id}") # User ID: 12345 # 执行取消订阅操作 except itsdangerous.BadSignature: print("Invalid or tampered token!")
-
账户激活链接: 当用户注册一个新账户时,你可以发送一个带有激活令牌的电子邮件。这个令牌可以通过
itsdangerous
生成,包含用户的 ID 和时间戳。用户点击链接后,你可以验证令牌的有效性并激活账户。from itsdangerous import URLSafeTimedSerializer serializer = URLSafeTimedSerializer('secret-key') user_id = 12345 token = serializer.dumps(user_id) activation_url = f"https://example.com/activate/{token}" print(activation_url) # https://example.com/activate/MTIzNDU.ZrHOUg.XKX0UgJqtICtvokMommg1hWpMmM
验证和激活账户:
token = '从URL中提取的token' try: user_id = serializer.loads(token, max_age=3600) # 令牌有效期为1小时 print(f"User ID: {user_id}") # User ID: 12345 # 执行账户激活操作 except itsdangerous.SignatureExpired: print("Activation link has expired!") except itsdangerous.BadSignature: print("Invalid or tampered token!")
-
无状态会话管理: 在某些 Web 应用中,你可以将用户会话数据签名后存储在 cookies 中,而不是在服务器上保存会话信息。这样可以减少对数据库的访问次数,提高性能。
from itsdangerous import URLSafeSerializer import flask app = flask.Flask(__name__) serializer = URLSafeSerializer(app.secret_key) @app.route('/set_session') def set_session(): session_data = {'user_id': 12345, 'role': 'admin'} token = serializer.dumps(session_data) response = flask.make_response("Session data set!") response.set_cookie('session', token) return response @app.route('/get_session') def get_session(): token = flask.request.cookies.get('session') try: session_data = serializer.loads(token) return f"Session data: {session_data}" except itsdangerous.BadSignature: return "Invalid or tampered session data!"
为什么不用 JWT
- 简化的设计:itsdangerous 的设计较为简单,没有 JWT 那样的复杂功能和多种算法选项。这减少了安全漏洞的可能性,因为它避免了算法选择和协商的问题。
- 适用场景:对于不需要复杂身份验证和加密功能的场景,itsdangerous 提供了简单且有效的解决方案。
总之,JWT 提供了更复杂和标准化的功能,但也带来了更多的安全挑战。itsdangerous 的设计简单,减少了这些挑战,但可能不适用于需要复杂认证机制的场景。
总结
itsdangerous 是一个强大的 Python 库,用于实现安全的数据签名和序列化。通过使用它,你可以在不受信任的环境中安全地传输数据,并确保数据在传输过程中的完整性。无论是生成安全的用户取消订阅链接、账户激活链接,还是在无状态会话管理中使用,itsdangerous 提供了灵活且高效的解决方案。
希望这篇文章帮助你更好地理解 itsdangerous 的功能及其应用场景。