bigywater.tech
Django · 128

Django Secret Key 的用途

SECRET_KEY 到底用来做什么?与其背文档,不如换一次密钥看什么会坏、什么不会。这篇用 override_settings 在同一个项目里切换密钥,逐项验证,并试 SECRET_KEY_FALLBACKS 做平滑轮换。

会失效的
signing 签名、已登录会话、密码重置令牌、signed_cookies 会话
不受影响的
密码哈希、CSRF 令牌(本实验里换密钥后仍通过)
SECRET_KEY_FALLBACKS
把旧密钥放进去,旧签名、会话、令牌继续有效

签名

实测 · 本机执行输出
  签名串(前 40 字符): eyJvcmRlciI6N30:1xC3rf:RTxlt1FQSgoBiWAlN…
  同一个密钥 A                            → loads 得到 {'order': 7}
  换成密钥 B                             → BadSignature: Signature "RTxlt1FQSgoBiWAlNaT3SiyQ3KVADU9gtL-dNQY
  密钥 B + SECRET_KEY_FALLBACKS=[A]    → loads 得到 {'order': 7}

Django 的很多功能都建立在 django.core.signing 之上,密钥泄漏就意味着别人能伪造这些签名。

会话与登录状态

实测 · 本机执行输出
  登录(密钥 A): True  /who/ → user=ann
  换成密钥 B                 → /who/ → user=anonymous
  密钥 B + fallback A      → /who/ → user=ann
  数据库里的会话行数(换密钥没有删除它们): 1

密码重置令牌

实测 · 本机执行输出
  密钥 A                   → check_token = True
  密钥 B                   → check_token = False
  密钥 B + fallback A      → check_token = True

不受影响的东西

实测 · 本机执行输出
  换密钥 B 后用密码登录: True
  密钥 A 下拿到的 CSRF 令牌,在密钥 B 下 POST → 200

CSRF 令牌不依赖 SECRET_KEY 这一点,只是在本实验的设置下观察到的。

signed_cookies 与空密钥

实测 · 本机执行输出
  登录: True
  密钥 A:/who/ → user=ann  cookie 长度 227
  密钥 B:/who/ → user=anonymous
  读取空的 SECRET_KEY → ImproperlyConfigured: The SECRET_KEY setting must not be empty.

分步演示

SECRET_KEY 的影响
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7 / Django 6.1.1(默认用 SQLite,其它数据库会在文中注明),用 django.test.Client 或真实的本机服务器进程实测;计时用 time.perf_counter,数字每次运行会有小幅抖动。SQLite;用 override_settings 在同一进程里切换密钥(A、B 是实验用的字符串);会话用 Client.login 创建
    • 没有验证:密钥泄漏后的具体攻击(本文只做防御侧验证)、SECRET_KEY_FALLBACKS 的数量上限、Django 内置之外的第三方包对密钥的使用、messages cookie、在多实例之间不同步密钥的后果
    京ICP备2026067502号-1京公网安备11010502063487号