You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中CSRF验证机制解析:为何不同令牌仍能通过校验?

Django CSRF令牌看似不同却验证通过的原因

这是因为Django的CSRF令牌采用了带随机掩码的设计,表面不同的令牌本质上对应同一个原始校验值,验证时会先解掩码再比较。

从你提供的代码看核心逻辑

_does_token_match函数并没有直接对比输入的两个令牌字符串,而是先对两个令牌分别调用_unmask_cipher_token进行解掩码处理,再用constant_time_compare比较处理后的结果:

def _does_token_match(request_csrf_token, csrf_token):
    # Assume both arguments are sanitized -- that is, strings of
    # length CSRF_TOKEN_LENGTH, all CSRF_ALLOWED_CHARS.
    return constant_time_compare(
        _unmask_cipher_token(request_csrf_token),
        _unmask_cipher_token(csrf_token),
    )

Django CSRF令牌的生成机制

Django的CSRF令牌由两部分组成:

  • 一个固定存储在用户session中的原始加密令牌(每个用户session对应唯一值)
  • 一个每次生成时随机生成的掩码

返回给前端的令牌,是通过将原始令牌与随机掩码进行异或运算后得到的结果。这意味着:同一个session下,每次生成的表面令牌都会不同,但它们解掩码后都会还原出同一个原始加密令牌。

你的测试场景解释

你测试的两个令牌:

  • Django自动生成返回的令牌
  • 通过get_token手动生成的令牌

都是基于同一个用户session中的原始加密令牌生成的,只是各自使用了不同的随机掩码。所以经过_unmask_cipher_token解掩码后,两者会得到完全相同的原始值,最终constant_time_compare返回True,验证通过。

这种设计的意义

带随机掩码的设计是为了提升安全性:即使攻击者嗅探到了某个前端令牌,也无法直接复用这个令牌发起CSRF攻击(因为下次请求生成的令牌掩码不同,但验证时只认解掩码后的原始值),同时避免了令牌长期固定带来的泄露风险。

内容的提问来源于stack exchange,提问作者BoostedAnimal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 20:27:24