序列化接口 — 这是危险的文档

来自菜鸟教程
Itsdangerous/docs/1.0.x/serializer
跳转至:导航、​搜索

序列化接口

签名接口 只对字符串进行签名。 为了对其他类型进行签名,Serializer 类提供了一个 dumps/loads 接口类似于 Python 的 json 模块,它将对象序列化为一个字符串然后签名.

使用 dumps() 对数据进行序列化和签名:

from itsdangerous.serializer import Serializer
s = Serializer("secret-key")
s.dumps([1, 2, 3, 4])
b'[1, 2, 3, 4].r7R9RhGgDPvvWl3iNzLuIIfELmo'

使用 loads() 验证签名并反序列化数据。

s.loads('[1, 2, 3, 4].r7R9RhGgDPvvWl3iNzLuIIfELmo')
[1, 2, 3, 4]

默认情况下,数据被序列化为 JSON。 如果安装了 simplejson,则优先于内置的 json 模块。 这个内部序列化器可以通过子类化来改变。

要记录和验证签名的年龄,请参阅 使用时间戳签名 。 要序列化为可在 URL 中安全使用的格式,请参阅 URL 安全序列化

所有类也接受盐参数。 该名称可能具有误导性,因为通常如果您想到密码学中的盐,您会期望盐与结果签名字符串一起存储,以防止彩虹表查找。 这种盐通常是公开的。

在它的危险中,就像在原始 Django 实现中一样,salt 有不同的用途。 您可以将其描述为命名空间。 如果您披露它仍然不重要,因为没有密钥就无法帮助攻击者。

假设您有两个要签名的链接。 您的系统上有可以激活用户帐户的激活链接,并且您有一个升级链接,可以将用户帐户升级为您通过电子邮件发送的付费帐户。 如果在这两种情况下您签署的只是用户 ID,则用户可以重复使用来自激活链接的 URL 中的变量部分来升级帐户。 现在,您可以在其中放置更多您签名的信息(例如意图:升级或激活),但您也可以使用不同的盐:

from itsdangerous.url_safe import URLSafeSerializer
s1 = URLSafeSerializer("secret-key", salt="activate")
s1.dumps(42)
'NDI.MHQqszw6Wc81wOBQszCrEE_RlzY'
s2 = URLSafeSerializer("secret-key", salt="upgrade")
s2.dumps(42)
'NDI.c0MpsD6gzpilOAeUPra3NShPXsE'

第二个序列化程序无法加载与第一个序列化程序一起转储的数据,因为盐不同:

s2.loads(s1.dumps(42))
Traceback (most recent call last):
  ...
itsdangerous.exc.BadSignature: Signature "MHQqszw6Wc81wOBQszCrEE_RlzY" does not match

只有具有相同盐的序列化程序才能加载数据:

s2.loads(s2.dumps(42))
42

应对失败

异常具有有用的属性,允许您在签名检查失败时检查有效负载。 这必须格外小心,因为那时您知道有人篡改了您的数据,但这可能对调试有用。

from itsdangerous.serializer import Serializer
from itsdangerous.exc import BadSignature, BadData

s = URLSafeSerializer("secret-key")
decoded_payload = None

try:
    decoded_payload = s.loads(data)
    # This payload is decoded and safe
except BadSignature as e:
    if e.payload is not None:
        try:
            decoded_payload = s.load_payload(e.payload)
        except BadData:
            pass
        # This payload is decoded but unsafe because someone
        # tampered with the signature. The decode (load_payload)
        # step is explicit because it might be unsafe to unserialize
        # the payload (think pickle instead of json!)

如果您不想检查属性以找出究竟出了什么问题,您还可以使用 loads_unsafe()

sig_okay, payload = s.loads_unsafe(data)

返回的元组中的第一项是一个布尔值,指示签名是否正确。


应用程序接口