前言
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工作流程中中间件执行顺序:

单个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]
# a[100]
print('views.py-----视图中的代码被执行了')
# return render(request, 'books/cook2.html', {'x':'渲染一下'})
def render():
print("触发 Template render()方法")
return HttpResponse("反悔了啊")
rep = HttpResponse("11123232")
rep.render = render
return rep
# 最后记得在配置文件下写入对应的中间件
访问对应的路径,模拟正常流程下render()渲染的结果
Exp1 ---> precess_request 4385889584
Exp2 ---> precess_request 4385889584
Exp1 ---> process_view
Exp1 <function exrp at 0x1052e2400> exrp
Exp2 ---> process_view
Exp2 <function exrp at 0x1052e2400> exrp
views.py-----视图中的代码被执行了
Exp2 process_template_response
Exp1 process_template_response
触发 Template render()方法
Exp2 ---> process_response
Exp1 ---> process_response
[22/May/2019 16:44:32] "GET /books/exrp/ HTTP/1.1" 200 12
再看一下如果视图渲染的时候错误打印
Exp1 ---> precess_request 4370030264
Exp2 ---> precess_request 4370030264
Exp1 ---> process_view
Exp1 <function exrp at 0x104640400> exrp
Exp2 ---> process_view
Exp2 <function exrp at 0x104640400> exrp
Exp2 list index out of range
Exp2 process_exception
Exp2 ---> process_response
Exp1 ---> process_response
[22/May/2019 16:50:29] "GET /books/exrp/ HTTP/1.1" 200 11
总结:
1.中间件的process_request和process_view这两个函数是在视图函数之前执行的
2.多个中间件,会按照配置文件的顺序执行,process_request和process_view是顺序执行,其他三个是逆序执行
3.中间件传递的都是同一个对象
4.如果视图正常渲染,不会执行process_exception方法,如果不正常,执行顺序逆序,有一个返回HTTPResponse则终端传递,直接传给process_response返回给客户端
5.当我们通过render()渲染的时候,会触发process_template_response函数,很少用这个方法
两张图详细描述了多个中间件执行顺序,可以配合上面的总概览图看


参考博客,内容非常详细
本文深入探讨Django框架中CSRF中间件的工作原理,包括设置、中间件参与流程及Token生成机制,通过源码分析揭示CSRF防御策略。
1001

被折叠的 条评论
为什么被折叠?



