django中csrf_token原理

为防止CSRF攻击,我们需要在html页面加入{% csrf_token %}这样的代码。

但是,当我们打开多个页面的时候,你会发现,每个页面的这个csrfmiddlewaretoken还不一样,如下代码所示:

//页面1的部分代码
<input type="hidden" name="csrfmiddlewaretoken" value="aPhlhBx4ellSgZbxDiBYwLqGd8pC3Pt0bkSD7wedsiKAuDIDwIYPh1XdklDmmGcI">

//页面2的部分代码
<input type="hidden" name="csrfmiddlewaretoken" value="RgE7JUyRySSAh28ONcirBD1slwrnz2fhSLfpzPf0MPhivGFUGCFimTyZsJF7STYZ">

如果你修改csrfmiddlewaretoken的值,验证失败。所以,简单了解一下django如何验证csrfmiddlewaretoken。

从settings.py文件的MIDDLEWARE的配置项中有csrf的配置。

如果用的是pycharm的话,按住ctrl+鼠标左键,直接跳转到框架源码文件。

其实关于csrfmiddlewaretoken的加解密主要就两个函数。

def _salt_cipher_secret(secret):
    """
    Given a secret (assumed to be a string of CSRF_ALLOWED_CHARS), generate a
    token by adding a salt and using it to encrypt the secret.
    """
    salt = _get_new_csrf_string()
    chars = CSRF_ALLOWED_CHARS
    pairs = zip((chars.index(x) for x in secret), (chars.index(x) for x in salt))
    cipher = ''.join(chars[(x + y) % len(chars)] for x, y in pairs)
    return salt + cipher


def _unsalt_cipher_token(token):
    """
    Given a token (assumed to be a string of CSRF_ALLOWED_CHARS, of length
    CSRF_TOKEN_LENGTH, and that its first half is a salt), use it to decrypt
    the second half to produce the original secret.
    """
    salt = token[:CSRF_SECRET_LENGTH]
    token = token[CSRF_SECRET_LENGTH:]
    chars = CSRF_ALLOWED_CHARS
    pairs = zip((chars.index(x) for x in token), (chars.index(x) for x in salt))
    secret = ''.join(chars[x - y] for x, y in pairs)  # Note negative values are ok
    return secret

下面写出简单的测试代码,来说明为什么每个页面的csrfmiddlewaretoken不一样,表单提交依然可以互不干扰验证通过。

其实csrfmiddlewaretoken字符串 = 随机salt字符串  拼接上  随机token字符串,其中,“随机token字符串”是根据“随机salt字符串”“密钥字符串”计算得出的

import django
import string


def get_secret(token):
    salt = token[:32]  # 前32位为加盐字符串
    token = token[32:]  # 后32位为token字符串
    chars = string.ascii_letters + string.digits  # 字符串为a-zA-Z0-9
    print('chars: ', chars)
    pairs = zip((chars.index(x) for x in token), (chars.index(x) for x in salt))
    secret = ''.join(chars[x - y] for x, y in pairs)
    print('secret: ', secret)  # 计算出密钥


if __name__ == '__main__':
    print('django version: ', django.VERSION)
    text = 'aPhlhBx4ellSgZbxDiBYwLqGd8pC3Pt0bkSD7wedsiKAuDIDwIYPh1XdklDmmGcI' # 表单中csrf_token的字符串,长度为64
    text2 = 'RstkB5GMKSzlbnJksqy2vOWobk00SEgASX4Cr0nVYPY3p1gqlQVTg4tVixeKbvZi' # cookie中csrf_token的字符串,长度为64
    get_secret(text)
    get_secret(text2)

最后,我们再回去看csrfmiddlewaretoken的加解密函数,就不难理解了。

参考:https://www.bootwiki.com/note/django-xss-csrf-token.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值