通过以下代码设置cookie:
response = HttpResponse()
response.set_signed_cookie("signed_cookie_name","signed_cookie_value","salt")
在客户端查看cookie后,显示结果:
Name :signed_cookie_name
Value :signed_cookie_value:1fPSBW:_JLMVkTZzxZe7aZr7KyjXwrsBBs
也就是说会把我加密之前的value也给打出来,这样合理么?有什么解决办法么?
Django 设计如此.
signed_cookie 只是加了签名的 cookie, 而不是被加密的 cookie.
signed_cookie 的作用是防止用户私自纂改.参考: Securing Web Cookies With Signatures
单纯的记录 uid 或者用户名在 cookie 中很容易被篡改(也是不建议将用户敏感信息记录在cookie中的原因), 万一攻击者把
uid=1
换成uid=2
岂不是可以访问uid=2
用户的资源了吗? 而如果换成uid=2:1fPjh2:iQGDDYNcgSYkIFqa2ixqakj6-gI
那么服务端不仅检验uid
, 还检验uid=2
后面的签名字段, 即是调用HttpRequest.get_signed_cookie(key=key, salt=salt)
, 这样即使用户把 cookie 中的 value 换成uid=2
, 但是没有签名, 服务端照样拒绝访问资源.另外, Django 的 cookie 签名是用的
Base64_with_hmac
, 参考: Source code for django.core.signing如果需要在 cookie 里设置被加密的 value, 需要自行对 value 进行加密(好像只能是对称加密), 比如使用
hashlib.sha256
{参考: hashlib — Secure hashes and message digests}:说句题外话,
对于 json 格式的字符串的加密, 目前推荐的方案是 JWT 规范, 参考: Introduction to JSON Web Tokens, 同样也是把信息暴露给了用户(但是一般的用户不能直接通过 token 看到信息, 需要稍加解密, 用户也不可能修改加密后的内容).
需要比较根本地防止中间人攻击, 加上 https 会是比较明智的选择.