Django的签名方法存在于django.core.signing模块中。 要签署一个值,首先实例化一个Signer实例:
>>> from django.core.signing import Signer
>>> signer = Signer()
>>> value = signer.sign('My string')
>>> value
'My string:GdMGD6HNQ_qdgxYP8yBZAdAIV1w'
签名会追加到冒号后面的字符串末尾。 您可以使用unsign方法检索原始值:
>>> original = signer.unsign(value)
>>> original
'My string'
如果签名或值以任何方式被更改,则会引发django.core.signing.BadSignature异常:
>>> from django.core import signing
>>> value += 'm'
>>> try:
... original = signer.unsign(value)
... except signing.BadSignature:
... print("Tampering detected!")
默认情况下,Signer类使用SECRET_KEY设置来生成签名。 您可以通过将其传递给Signer构造函数来使用不同的秘密:
>>> signer = Signer('my-other-secret')
>>> value = signer.sign('My string')
>>> value
'My string:EkfQJafvGyiofrdGnuthdxImIJw'
`django.core.signing.Signer`
返回一个签名者,它使用密钥来生成签名并分隔值来分隔值。 sep不能在URL安全的base64字母表中。 此字母表包含字母数字字符,连字符和下划线。
使用盐论据
如果您不希望每个特定字符串的出现都具有相同的签名散列,则可以将可选的salt参数用于Signer类。 使用salt将使用salt和SECRET_KEY对签名哈希函数进行种子处理:
>>> signer = Signer()
>>> signer.sign('My string')
'My string:GdMGD6HNQ_qdgxYP8yBZAdAIV1w'
>>> signer = Signer(salt='extra')
>>> signer.sign('My string')
'My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw'
>>> signer.unsign('My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw')
'My string'
以这种方式使用salt将不同的签名放入不同的名称空间。 来自一个名称空间(特定salt值)的签名不能用于验证使用不同salt设置的不同名称空间中的相同纯文本字符串。 其结果是防止攻击者使用在代码中的一个位置生成的签名字符串作为输入到正在生成(并验证)使用不同salt的签名的另一条代码。
与你的SECRET_KEY不同,你的盐论并不需要保密。
验证时间戳值
TimestampSigner是Signer的一个子类,它为该值附加了一个签名的时间戳。 这允许您确认在指定的时间段内创建了一个有符号值:
>>> from datetime import timedelta
>>> from django.core.signing import TimestampSigner
>>> signer = TimestampSigner()
>>> value = signer.sign('hello')
>>> value
'hello:1NMg5H:oPVuCqlJWmChm1rA2lyTUtelC-c'
>>> signer.unsign(value)
'hello'
>>> signer.unsign(value, max_age=10)
...
SignatureExpired: Signature age 15.5289158821 > 10 seconds
>>> signer.unsign(value, max_age=20)
'hello'
>>> signer.unsign(value, max_age=timedelta(seconds=20))
'hello'
`sign(value)` signs `value` and appends the current timestamp.
unsign(value,max_age = None)检查值是否小于max_age秒之前的签名,否则引发SignatureExpired。 max_age参数可以接受一个整数或一个datetime.timedelta对象。
保护复杂的数据结构
如果你想保护一个列表,元组或字典,你可以使用签名模块的转储和加载函数。 这些模仿Python的pickle模块,但在引擎盖下使用JSON序列化。 JSON确保即使您的SECRET_KEY被盗,攻击者也无法通过利用pickle格式执行任意命令:
>>> from django.core import signing
>>> value = signing.dumps({"foo": "bar"})
>>> value
'eyJmb28iOiJiYXIifQ:1NMg1b:zGcDE4-TCkaeGzLeW9UQwZesciI'
>>> signing.loads(value)
{'foo': 'bar'}
由于JSON的性质(列表和元组之间没有本地区别),如果传递一个元组,您将从signing.loads(object)获得一个列表:
>>> from django.core import signing
>>> value = signing.dumps(('a','b','c'))
>>> signing.loads(value)
['a', 'b', 'c']
安全中间件
如果您的部署情况允许,让前端Web服务器执行SecurityMiddleware提供的功能通常是个好主意。 这样,如果存在没有被Django提供服务的请求(如静态媒体或用户上传的文件),它们将具有与对Django应用程序的请求相同的保护。
django.middleware.security.SecurityMiddleware为请求/响应周期提供了多项安全增强功能。 每个人都可以独立启用或禁用设置。
-
SECURE_BROWSER_XSS_FILTER
-
SECURE_CONTENT_TYPE_NOSNIFF
-
SECURE_HSTS_INCLUDE_SUBDOMAINS
-
SECURE_HSTS_SECONDS
-
SECURE_REDIRECT_EXEMPT
-
SECURE_SSL_HOST
-
SECURE_SSL_REDIRECT
有关安全标题和这些设置的更多信息,请参阅第17章。
下一步是什么?
在下一章中,我们将详细介绍第1章中的快速安装指南,并介绍Django的一些其他安装和配置选项。
网友评论