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的值做对比,对比成功通过校验。

最新文章

  1. ECharts数据图表系统? 5分钟上手!
  2. 遭遇Web print
  3. 使用 Eclipse 调试 Java 程序的技巧
  4. ASP.NET MVC5利用EF,反向自动生成数据库
  5. $q服务的API详解
  6. Leetcode006 ZigZag Conversion
  7. OpenOffice的安装与启动2
  8. .net source code
  9. 在iframe中获取iframe外的对象
  10. Mysql学习(慕课学习笔记1)启动、登录及常用命令
  11. mysql 修改表结构的字段名
  12. 单词方阵 洛谷 P1101
  13. Asp.net MVC4高级编程学习笔记-视图学习第一课20171009
  14. 关于require.js的模块化开发
  15. 学习TensorFlow,调用预训练好的网络(Alex, VGG, ResNet etc)
  16. DataPipeline丨金融行业如何统一管理单个任务下所有API的同步情况
  17. 【python 字符串】 字符串的相关方法(一)
  18. 电子科技大学第九届ACM趣味程序设计竞赛(热身赛)题解
  19. java web中验证码生成的demo
  20. Vue语法学习第四课(2)——class与style的绑定

热门文章

  1. 【NOIP2016提高A组8.12】奇袭
  2. LeetCode--015--三数之和(python)
  3. 解决使用脚手架构建项目缺失node_modules文件夹文件问题
  4. 认识.net Framework
  5. VS2015编译问题:模块对于 SAFESEH 映像是不安全的
  6. docker 安装MongoDB以及设置用户
  7. BZOJ 1029 建筑抢修(贪心堆)
  8. UE4网络功能相关笔记
  9. SpringBoot属性配置-第三章
  10. BigDecimal保留两位小数,或指定精确的位数