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