CSRF和中间件
CSRF使用
说明csrf存在cookie中
全局使用
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', ]
局部使用
先导入 from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。 @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
前端使用
1.通过引入js实现
function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
2、作为参数传入
<script> var csrftoken = $.cookie('csrftoken'); $(function () { $('#btn').click(function () { $.ajax({ url:'/login/', type:"POST", data:{'username':'root','pwd':'123123'}, header:{'X-CSRFtoken':csrftoken}, success:function (arg) { } }) }) }) </script>
3、自定义form引入
{% csrf_token %}
中间件
1.概述
定义:中间件是在wsgi之后 urls.py之前 在全局 操作Django请求和响应的模块!
# 中间件的相关设置 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', # request.session 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'my_middleware.OoXx', 'my_middleware.MD2', ]
2.中间件的五种方法
(1) .process_request(self,request)
请求来时执行,不写直接跳过,执行下一个中间件;当有return HttpResonse时,下面中间件不再执行。
执行顺序:
按照注册的顺序(在settings.py里面设置中 从上到下的顺序)
何时执行:
请求从wsgi拿到之后
返回值:
返回None,继续执行后续的中间件的process_request方法
返回response , 不执行后续的中间件的process_request方法
(2) process_view(self, request, callback, callback_args, callback_kwargs)
先执行process_request,执行完后,再从起始执行proces_view
执行顺序:
按照注册的顺序(在settings.py里面设置中 从上到下的顺序)
何时执行:
在urls.py中找到对应关系之后 在执行真正的视图函数之前
返回值:
返回None,继续执行后续的中间件的process_view方法
返回response,
(3) process_template_response(self,request,response)
如果Views中的函数返回的对象中,具有render方法,此方法执行
执行顺序:
按照注册顺序的倒序(在settings.py里面设置中 从下到上的顺序)
何时执行:
视图函数执行完,在执行视图函数返回的响应对象的render方法之前
返回值:
返回None,继续执行后续中间件的process_exception
返回response,
(4). process_exception(self, request, exception)
异常触发执行,当views.py函数执行出错后,此方法执行;出错时,最低层的exception优先级最高,执行最近的一个,然后执行respnse方法
执行顺序:
按照注册顺序的倒序(在settings.py里面设置中 从下到上的顺序)
何时执行:
视图函数中抛出异常的时候才执行
返回值:
返回None,继续执行后续中间件的process_exception
返回response,
(5). process_response(self, request, response)
请求返回时执行,不写时直接跳过,执行下一个中间件;当有return HttpResonse时,会替换原数据
执行顺序:
按照注册顺序的倒序(在settings.py里面设置中 从下到上的顺序)
何时执行:
请求有响应的时候
返回值:
必须返回一个response对象
以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户
Django调用 注册的中间件里面五个方法的顺序:
1. process_request
urls.py
2. process_view
view
3. 有异常就执行 process_exception
4. 如果视图函数返回的响应对象有render方法,就执行process_template_response
5. process_response
3.自定义中间件
创建文件 my_middleware.py
from django.shortcuts import HttpResponse, redirect """ 自定义的中间件 """ from django.utils.deprecation import MiddlewareMixin # 定义一个可以访问的白名单 URL = ["/oo/", "/xx/", "/haha/"] class OoXx(MiddlewareMixin): def process_request(self, request): print("这是我的第一个中间件:OoXx!") print(id(request)) # print(request.path_info) # # 如果用户访问的URL 在 白名单里面 # if request.path_info in URL: # return # # 否则 直接返回一个 响应 不走视图那部分了 # else: # return HttpResponse("gun!") def process_response(self, request, response): """ :param request: 是浏览器发来的请求对象 :param response: 是视图函数返回的响应对象 :return: """ print("这是OOXX中间件里面的 process_response") # return response return HttpResponse("hahahaha") def process_view(self, request, view_func, view_args, view_kwargs): """ :param request: 浏览器发来的请求对象 :param view_func: 将要执行的视图函数的名字 :param view_args: 将要执行的视图函数的位置参数 :param view_kwargs: 将要执行的视图函数的关键字参数 :return: """ print("ooxx里面的process_view") print(view_func, type(view_func)) return HttpResponse("ooxx:process_view") def process_exception(self, request, exception): print(exception) print("ooxx里面的process_exception") return redirect("http://www.baidu.com") def process_template_response(self, request, response): print("ooxx 中的process_template_response") return response def process_request(self, request): request.s10 = {"is_login": 1, "name": "s10"} class MD2(MiddlewareMixin): # def process_request(self, request): # print("这是我的第二个中间件:MD2!") # print(id(request)) # # def process_response(self, request, response): # print("这是MD2中间件里面的 process_response") # return response # # def process_view(self, request, view_func, view_args, view_kwargs): # print("MD2里面的process_view") # print(view_func, type(view_func)) # return HttpResponse("md2:process_view") # def process_exception(self, request, exception): # print(exception) # print("MD2里面的process_exception") # def process_template_response(self, request, response): # print("MD2 中的process_template_response") # return response def process_request(self, request): print(request.s10.get("is_login"))
注册
# 中间件的相关设置 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', # request.session 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'my_middleware.OoXx', 'my_middleware.MD2', ]
请求测试
from django.shortcuts import render, HttpResponse, redirect # Create your views here. def index(request): print("这是app01里面的index视图函数...") # raise ValueError("sb") rep = HttpResponse("O98K") print("视图函数中的s10:", request.s10) def render(): print("我是index视图函数内部的render方法") return redirect("http://www.luffycity.com") rep.render = render return rep