csrf的中间件

源码简略分析:

    def process_request(self, request):
# 从cookies中获取csrf_token
csrf_token = self._get_token(request)
if csrf_token is not None:
# Use same token next time.
# 将csrf_token添加到request的头部信息中
request.META['CSRF_COOKIE'] = csrf_token def process_view(self, request, callback, callback_args, callback_kwargs):
# csrf校验已经完成
if getattr(request, 'csrf_processing_done', False):
return None # Wait until request.META["CSRF_COOKIE"] has been manipulated before
# bailing out, so that get_token still works
# 豁免
if getattr(callback, 'csrf_exempt', False):
return None # Assume that anything not defined as 'safe' by RFC7231 needs protection
# 如果请求方式不在其中
if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
# 如果不需要进行csrf校验
if getattr(request, '_dont_enforce_csrf_checks', False):
# Mechanism to turn off CSRF checks for test suite.
# It comes after the creation of CSRF cookies, so that
# everything else continues to work exactly the same
# (e.g. cookies are sent, etc.), but before any
# branches that call reject().
return self._accept(request)
# 如果请求方式是https
if request.is_secure():
# Suppose user visits http://example.com/
# An active network attacker (man-in-the-middle, MITM) sends a
# POST form that targets https://example.com/detonate-bomb/ and
# submits it via JavaScript.
#
# The attacker will need to provide a CSRF cookie and token, but
# that's no problem for a MITM and the session-independent
# secret we're using. So the MITM can circumvent the CSRF
# protection. This is true for any HTTP connection, but anyone
# using HTTPS expects better! For this reason, for
# https://example.com/ we need additional protection that treats
# http://example.com/ as completely untrusted. Under HTTPS,
# Barth et al. found that the Referer header is missing for
# same-domain requests in only about 0.2% of cases or less, so
# we can use strict Referer checking.
referer = force_text(
request.META.get('HTTP_REFERER'),
strings_only=True,
errors='replace'
)
if referer is None:
return self._reject(request, REASON_NO_REFERER) referer = urlparse(referer) # Make sure we have a valid URL for Referer.
if '' in (referer.scheme, referer.netloc):
return self._reject(request, REASON_MALFORMED_REFERER) # Ensure that our Referer is also secure.
if referer.scheme != 'https':
return self._reject(request, REASON_INSECURE_REFERER) # If there isn't a CSRF_COOKIE_DOMAIN, require an exact match
# match on host:port. If not, obey the cookie rules (or those
# for the session cookie, if CSRF_USE_SESSIONS).
good_referer = (
settings.SESSION_COOKIE_DOMAIN
if settings.CSRF_USE_SESSIONS
else settings.CSRF_COOKIE_DOMAIN
)
if good_referer is not None:
server_port = request.get_port()
if server_port not in ('443', '80'):
good_referer = '%s:%s' % (good_referer, server_port)
else:
# request.get_host() includes the port.
good_referer = request.get_host() # Here we generate a list of all acceptable HTTP referers,
# including the current host since that has been validated
# upstream.
good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
good_hosts.append(good_referer) if not any(is_same_domain(referer.netloc, host) for host in good_hosts):
reason = REASON_BAD_REFERER % referer.geturl()
return self._reject(request, reason)
# 从MATA中获取'CSRF_COOKIE'(在process_request中设置的)
csrf_token = request.META.get('CSRF_COOKIE')
# csrf_token是空,校验失败
if csrf_token is None:
# No CSRF cookie. For POST requests, we insist on a CSRF cookie,
# and in this way we can avoid all CSRF attacks, including login
# CSRF.
return self._reject(request, REASON_NO_CSRF_COOKIE) # Check non-cookie token for match.
request_csrf_token = ""
if request.method == "POST":
try:
# 在POST提交的数据中获取'csrfmiddlewaretoken'
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
except IOError:
# Handle a broken connection before we've completed reading
# the POST data. process_view shouldn't raise any
# exceptions, so we'll ignore and serve the user a 403
# (assuming they're still listening, which they probably
# aren't because of the error).
pass
# 如果POST数据中没有,则尝试从MATA中获取'x-csrftoken'
if request_csrf_token == "":
# Fall back to X-CSRFToken, to make things easier for AJAX,
# and possible for PUT/DELETE.
request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '') request_csrf_token = _sanitize_token(request_csrf_token)
# 如果request_csrf_token和csrf_token不匹配,则校验失败
if not _compare_salted_tokens(request_csrf_token, csrf_token):
return self._reject(request, REASON_BAD_TOKEN) return self._accept(request) def process_response(self, request, response):
# 如果不需要需要重新设置csrftoken
if not getattr(request, 'csrf_cookie_needs_reset', False):
if getattr(response, 'csrf_cookie_set', False):
return response if not request.META.get("CSRF_COOKIE_USED", False):
return response # Set the CSRF cookie even if it's already set, so we renew
# the expiry timer.
# 依据META中的'CSRF_COOKIE'的值来设置csrftoken
self._set_token(request, response)
response.csrf_cookie_set = True
return response

csrf相关的装饰器:

from django.views.decorators.csrf import csrf_exempt, csrf_protect
# csrf_exempt 豁免csrf校验
# csrf_protect 强制进行csrf校验 from django.utils.decorators import method_decorator
@method_decorator(csrf_exempt, name='dispatch')
# csrf_exempt要加在CBV上,只能加dispatch上

csrf校验:

/1.想要能通过csrf校验的前提条件: 必须要有 csrftokencookie

  1. {% csrf_token %},在POST请求数据中添加csrfmiddlewaretoken

  2. from django.views.decorators.csrf import ensure_csrf_cookie

/2.从cookie获取csrftoken的值 与 POST提交的数据中的csrfmiddlewaretoken的值做对比(如果从request.POST中获取不到csrfmiddlewaretoken的值,会尝试从请求头META中获取x-csrftoken的值)拿这个值与csrftoken的值做对比,对比成功通过校验。

csrf的中间件的更多相关文章

  1. Django(六)Session、CSRF、中间件

    大纲 二.session 1.session与cookie对比 2.session基本原理及流程 3.session服务器操作(获取值.设置值.清空值) 4.session通用配置(在配置文件中) 5 ...

  2. Python之路-(Django(csrf,中间件,缓存,信号,Model操作,Form操作))

    csrf 中间件 缓存 信号 Model操作 Form操作 csrf: 用 django 有多久,我跟 csrf 这个概念打交道就有久了. 每次初始化一个项目时都能看到 django.middlewa ...

  3. Django(5) session登录注销、csrf及中间件自定义、django Form表单验证(非常好用)

    一.Django中默认支持Session,其内部提供了5种类型的Session供开发者使用: 数据库(默认) 缓存 文件 缓存+数据库 加密cookie 1.数据库Session 1 2 3 4 5 ...

  4. django学习之- CSRF及中间件

    CSRF # 表示django全局发送post请求均需要字符串验证功能:防止跨站请求伪造的功能工作原理:客户端访问服务器端,在服务器端正常返回给客户端数据的时候,而外返回给客户端一段字符串,等到客户端 ...

  5. [Python自学] day-22 (1) (Session、CSRF、中间件)

    一.响应函数补充 三种返回响应的方式: return HttpResponse() return render() return redirect() HttpResponse: 除了能够返回字符串, ...

  6. python 全栈开发,Day87(ajax登录示例,CSRF跨站请求伪造,Django的中间件,自定义分页)

    一.ajax登录示例 新建项目login_ajax 修改urls.py,增加路径 from app01 import views urlpatterns = [ path('admin/', admi ...

  7. django-cbv模式-csrf中间件

    1. django模式 def users(request): user_list = ['alex','oldboy'] return HttpResponse(json.dumps((user_l ...

  8. Django-中间件-csrf扩展请求伪造拦截中间件-Django Auth模块使用-效仿 django 中间件配置实现功能插拔式效果-09

    目录 昨日补充:将自己写的 login_auth 装饰装在 CBV 上 django 中间件 django 请求生命周期 ***** 默认中间件及其大概方法组成 中间件的执行顺序 自定义中间件探究不同 ...

  9. django csrf 中间件

    CSRF和中间件 CSRF使用 说明csrf存在cookie中 全局使用 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', ...

随机推荐

  1. Django【第10篇】:Django之分页初级版本

    分页和中间件 一.分页 Django的分页器(paginator) view.py from django.shortcuts import render,HttpResponse # Create ...

  2. NOIP2017 D1T1 小凯的疑惑

    洛谷P3951 看到题目,很容易想到这一题是求使ax+by=c(a,b,c∈N)无非负整数解的最大c 由裴蜀定理可知方程一定有整数解(a,b互素,gcd(a,b)=1|c) 解法一:暴力枚举 看到题目 ...

  3. js 获取滚动位置,滚动到指定位置,平滑滚动

    1.获取当前滚动条位置信息 var top = dom.scrollTop; // 获取y轴上的滚动位置 var left = dom.scrollLeft; // 获取x轴上的滚动位置 2.滚动到指 ...

  4. linux运维、架构之路-linux目录结构

    1.linux重要目录 重要目录 说明 /etc 存放系统配置文件.服务启动命令的目录 /root 超级管理员的家目录 /sbin和usr/sbin 超级用户命令的目录 /boot 系统引导程序所在的 ...

  5. Spring Boot文件上传

    一.创建一个简单的包含WEB依赖的SpringBoot项目 二.配置文件上传的文件大小限制 # 上传文件总的最大值spring.servlet.multipart.max-request-size=1 ...

  6. Eclipse设置类和方法的注释模板

    一.打开设置模板的窗口:Window->Preference->Java->Code Style->Code Template展开Comments,最常用的就是类和方法的注释, ...

  7. spring中试用junit4测试

    一:加入jar包 <!-- 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId& ...

  8. mysql DISTINCT语句 语法

    mysql DISTINCT语句 语法 作用:用于返回唯一不同的值. 语法:SELECT DISTINCT 列名称 FROM 表名称.扬州大理石量具 mysql DISTINCT语句 示例 //从表中 ...

  9. nginx修改默认运行80端口的方法

    修改方法 很简单,修改nginx的配置文件, 对应的值,如图: 将其改为别的端口号,就可以了.

  10. 使用JLDAP操作LDAP,包含匿名连接、ldif导入导出、获取根节点、对数据的操作、LDAP错误码解析等

    bean类 package com.cn.ccc.ggg.ldap.model; import javax.persistence.Entity; import javax.persistence.T ...