CSRF
CSRF,跨站请求伪造是一种挟持用户在当前已登陆的web站点应用程序上执行非本意的操作攻击方法,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。
Django的CSRF中间件验证就可以有效地杜绝此类恶意攻击,原理就是Django在内部会对通过验证请求的客户端再做一次加密验证,该加密方式只有Django自己知道,客户端即使携带session反解密CSRF不成功也会拒绝访问;这是Django生命请求周期中必经的一步,由此我们也可以引出中间件的概念及一般的自定义中间件使用方法
在setting中开启CSRF验证
开启后浏览器携带的CSRF验证信息
由于开启了全局CSRF验证,以后我们每提交的一个页面POST请求,Django都会要求验证,所以我们必须在页面加载该配置信息,有2种方式
1)前端页面直接提交
<form action="/login/" method="POST"> // 在from表单中添加模版信息 {% csrf_token %} <input type="text" name="user" /> <input type="text" name="pwd" /> <input type="submit" value="提交" /> </form>
2)ajax提交
$(function(){ // 这是ajax全局事件 发ajax请求之前做操作 $.ajaxSetup({ beforeSend: function(xhr,settings){ xhr.setRequestHeader(‘X-CSRFtoken‘, $.cookie(‘csrftoken‘)); } }); $(‘#btn1‘).click(function () { $.ajax({ url: ‘/login/‘, type:"GET", data: {‘user‘: ‘root‘, ‘pwd‘: ‘123‘}, // 在请求头中加入CSRFtoken 如果上面已经设置了ajax全局绑定 就可以省略 // headers: {‘X-CSRFtoken‘: $.cookie(‘csrftoken‘)}, success:function(arg){ } }) }); })
后台我们可以通过X-CSRFtoken获取
# print(settings.CSRF_HEADER_NAME) # HTTP_X_CSRFTOKEN # X-CSRFtoken
对于在中间件中启用CSRF后,意味着全局view函数都会被要求验证,如果有需求某几个页面views不需要,可以添加下面的装饰器
// 取消CSRF验证保护 @csrf_exempt def index(request): // 单独开启CSRF验证保护 @csrf_protect def index(request):
中间件
Django中的中间件,其实是一个类,在请求到来和结束后,Django会根据自己的规则在合适的时机执行中间件中相应的方法,如上面图一我们看到的MIDDLEWARE里面的就是Django中已经注册在使用的中间件
1)自定义中间件
在中间件中我们可以自定义5种方法
// 1)接受请求方法 process_request(self,request) // 2)接受视图方法 process_view(self, request, callback, callback_args, callback_kwargs) // 3)判断返回函数是否有render方法 process_template_response(self,request,response) // 4)异常处理方法 process_exception(self, request, exception) // 5)回复请求 process_response(self, request, response)
在app同级目录建立中间件目录Middle,新建中间件文件m1.py
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse // 定义class 需要继承MiddlewareMixin class Row1(MiddlewareMixin): def process_request(self,request): print(‘request_row_1‘) def process_view(self, request, view_func, view_func_args, view_func_kwargs): print(‘view_row_1‘) def process_response(self, request, response): print(‘process_row_1‘) return response class Row2(MiddlewareMixin): def process_request(self,request): print(‘request_row_2‘) def process_view(self, request, view_func, view_func_args, view_func_kwargs): print(‘view_row_2‘) def process_response(self, request, response): print(‘process_row_2‘) return response
在setting中注册中间件,注意我们放置位置,运行程序我们看看Django中间件的运行顺序是什么
路由URL配置
urlpatterns = [ url(r‘^test/(?P<nid>\d+)$‘, views.test), ]
views视图函数配置
def test(request,nid): print(‘view --> ‘) return render(request, ‘index.html‘)
运行结果
所以中间件的运行过程其实如下图所示
Django收到用户请求后,会依次被中间件处理,先经过request方法,等执行到最后一个中间件,经过一次路由匹配找到view对应的函数,回头去执行各个中间件的view方法,此时请求携带的额外参数被封装在view_func参数中,最后由服务器端views视图函数返回数据,中间件通过reponse传递消息给用户。
此时中间件的作用就很明显了,可以在请求真正到达服务器后端前做相应操作,比如拦截操作
如果在中间件Row_2中对该请求拦截只需要直接return HttpResponse信息
class Row2(MiddlewareMixin): def process_request(self,request): print(‘request_row_2‘) return HttpResponse(‘row_2_no...‘)
此时我们看中间件执行过程,请求在Row_2中间件处已经被拦截,并没有达到服务器后端views
异常处理
如果服务端views函数发生异常,一般Django会直接报错给用户界面,这样对用户来说不够友好,所以我们可以在中间层面对一些异常拦截,并处理
def test(request,nid): print(‘view --> ‘) // 模拟处理异常 i = int(‘abc‘) return render(request, ‘index.html‘)
编辑中间件函数
class Row2(MiddlewareMixin): ... // Row_2中加入异常处理 def process_exception(self, request, exception): if isinstance(exception, ValueError): return HttpResponse(‘数据处理出现异常。。‘)
界面显示