django中间件CsrfViewMiddleware源码分析,探究csrf实现

本文详细分析了Django的CsrfViewMiddleware中间件,包括流程、关键方法如get_token,以及如何防止CSRF攻击。通过理解中间件的工作原理,可以更好地了解Django的CSRF保护策略。
摘要由CSDN通过智能技术生成

Django Documentation

csrf保护基于以下:
1. 一个CSRF cookie 基于一个随机生成的值,其他网站无法得到。此cookie由CsrfViewMiddleware产生。它与每个调用django.middleware.csrf.get_token()(这是一个用于取回CSRF token的方法)的响应一起发送,如果它尚未在请求上设置的话。
为了防止BREACH攻击,token不仅仅是秘密;随机的salt被置于secret之前并用来加密它。出于安全原因,每次用户登录时都会更改密钥的值。

  1. 所有传出POST表单中都有一个名为csrfmiddlewaretoken的隐藏表单字段。此字段的值同样是秘密的值。salt添加到它并用于加扰它。每次调用get_token()时都会重新生成salt,以便在每个此类响应中更改表单字段值。这部分由template的{% csrf_token %}完成。

  2. 对于未使用HTTP GETHEADOPTIONSTRACE的所有传入请求,必须带有CSRF cookie,并且csrfmiddlewaretoken字段必须存在且正确。如果不是,用户将收到403错误。
    验证csrfmiddlewaretoken字段值时,只将secret而不是整个token与cookie值中的secret进行比较。这允许使用不断变化的token。虽然每个请求都可以使用自己的token,但secret仍然是所有人共同的。
    此检查由CsrfViewMiddleware完成。

  3. 此外,对于HTTPS请求,严格的引用检查由CsrfViewMiddleware完成。这意味着即使子域可以在您的域上设置或修改cookie,它也不能强制用户发布到您的应用程序,因为该请求不会来自您自己的确切域。 这也解决了在使用会话独立秘密时在HTTPS下可能发生的中间人攻击,因为即使在HTTPS下与站点通信时,HTTP Set-Cookie标头(不幸)也被客户接受了。 。 (对HTTP请求不进行引用检查,因为在HTTP下,Referer头的存在不够可靠。) 如果设置了CSRF_COOKIE_DOMAIN设置,则会将引用者与其进行比较。此设置支持子域。例如,CSRF_COOKIE_DOMAIN ='.example.com'将允许来自www.example.comapi.example.com的POST请求。如果未设置该设置,则referer必须与HTTP Host标头匹配。 可以使用CSRF_TRUSTED_ORIGINS设置将已接受的引用扩展到当前主机或cookie域之外。

流程图

这里写图片描述

CsrfViewMiddleware.process_request

# django/middleware/csrf.py
class CsrfViewMiddleware(MiddlewareMixin):
    def process_request(self, request):
        csrf_token = self._get_token(request)
        # 第一次访问,csrf_token返回None,

        if csrf_token is not None:
            # Use same token next time.
            request.META['CSRF_COOKIE'] = csrf_token
            # request.META 是一个 Python 字典,包含了所有本次 HTTP 请求的 Header
            # 信息,比如用户 IP 地址和用户Agent(通常是浏览器的名称和版本号)。
settings = LazySettings()

这是一个惰性加载, 参考
- Django 源码阅读(二): settings懒加载

- django/conf/global_settings.py

方法_get_token,从名字上来看就是获取token,_get_token在后面多处地方都有用到

# django/middleware/csrf.py
def _get_token(self, request):
    # CSRF_USE_SESSIONS在django/conf/global_settings.py,默认为False,执行else
    if settings.CSRF_USE_SESSIONS:
        try:
            return request.session.get(CSRF_SESSION_KEY)
        except AttributeError:
            raise ImproperlyConfigured(
                'CSRF_USE_SESSIONS is enabled, but request.session is not '
                'set. SessionMiddleware must appear before CsrfViewMiddleware '
                'in MIDDLEWARE%s.' % ('_CLASSES' if settings.MIDDLEWARE is None else '')
            )
    else:
        try:
            cookie_token = request.COOKIES[settings.CSRF_COOKIE_NAME]
            # CSRF_SESSION_KEY= "csrftoken"
        except KeyError:
            # 第一次访问的时候 request.COOKIES = {},所以直接返回
            return None

        csrf_token = _sanitize_token(cookie_token)
        # csrf 对不上 cookie里 的 token,标记csrf_cookie_needs_reset=True,
        # 在process_response的方法中判定
        if csrf_token != cookie_token:
            # Cookie token needed to be replaced;
            # the cookie needs to be reset.
            request.csrf_cookie_needs_reset = True
        return csrf_token
# /django/middleware/csrf.py

CSRF_SECRET_LENGTH = 32
CSRF_TOKEN_LENGTH = 2 * CSRF_SECRET_LENGTH

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值