前言
XSS和CSRF攻击的基础原理这里就不介绍了,之前写了一篇文章单独介绍的很详细了,传送门,这里我们直接以Django为分析对象,分析中间件csrf生成原理以及防范Token如何运作的。
Settings文件
Setting.py中有茫茫多的配置选项。传送门
CSRF中间件
官方文档介绍的也是表面,本文通过源码层面直接分析流程
官方文档针对CSRF的介绍以及参数配置 传送门
Django全流程中间件参与过程
- 是一个轻量级,底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入和输出
- 激活:添加到Django配置文件的
MIDDLEWARE
中
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
上面的第四个就是我们这里要详细分析的CSRF中间件。
Django中中间件最多可以定义五个方法:
process_request(self,request)
process_view(self, request, view_func, view_args, view_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)
Django工作流程中中间件执行顺序:
1.请求进入到Django后,Django接收到第一个请求会调用中间件的初始化方法
__init__
,处理请求之前会按中间件的注册顺序执行每个中间件中的process_request
方法。如果所有的中间件的process_request
方法return None
,则进入路由映射,进行url匹配,通过规则确认请求由哪个视图处理,如果是return HTTPResponse
,则调用process_response
返回到客户端
2.依次按顺序执行中间件中的process_view
方法
如果某个中间件的process_view
方法没有return HttpResponse
,则根据第1步中匹配到的URL执行对应的视图函数或视图类(process_view
)在views.py
执行之前
如果某个中间件的process_view
方法中返回了return HttpRespons
,则后面的视图函数或视图类不会执行,程序会执行process_response
返回客户端
3.视图函数或者视图类接收Request,通过模型Model与数据库交互,获取数据交给模板引擎进行渲染,如果视图函数或视图类中使用render()
方法来向客户端返回数据,则会触发中间件中的process_template_response
方法,response
函数都是通过注册的逆序进行调用,必须返回response
才能继续转发,否则程序排除异常
4.随后视图函数或视图类执行计算渲染,如果没有任何异常,会按照中间件的注册顺序逆序执行中间件中的process_response
方法
如果中间件中定义了return response
,程序会正常执行,把视图函数或视图类的执行结果返回给客户端,否则程序会抛出异常
5.在第三步,程序在视图函数或视图类的正常执行过程中
如果出现异常,则会执行按顺序执行中间件中的process_exception
方法,该方法也是逆序执行的,如果某个中间件的process_exception
方法中定义了return语句,则终端传递中间件中的process_exception
函数,转发给process_response
处理后返回给客户端
单个CSRF中间件详细流程图如下
根据上面的步骤,验证了一下多个中间件组合调用的顺序
# 两个中间件代码
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class Exp1(MiddlewareMixin):
def process_request(self,request):
print('Exp1 ---> precess_request %s'%id(request))
def process_response(self, request, response):
print('Exp1 ---> process_response')
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print('Exp1 ---> process_view')
print('Exp1',view_func, view_func.__name__)
def process_exception(self, request, exception):
print('Exp1',exception)
print('Exp1','process_exception')
# return HttpResponse('卧槽,挂了啊')
def process_template_response(self, request, response):
print('Exp1','process_template_response')
return response
class Exp2(MiddlewareMixin):
def process_request(self, request):
print('Exp2 ---> precess_request %s'%id(request))
print()
def process_response(self, request, response):
print('Exp2 ---> process_response')
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print('Exp2 ---> process_view')
print('Exp2', view_func, view_func.__name__)
print()
def process_exception(self, request, exception):
print('Exp2', exception)
print('Exp2', 'process_exception')
return HttpResponse('enenenen???')
def process_template_response(self, request, response):
print('Exp2','process_template_response')
return response
# 视图代码
def exrp(request):
# a = [1, 2, 3]</