一 、CSRF中间件 :CSRF跨站请求伪造
如果就简单些一个登录表格的页面,提交这个属于跨站提交,这时候要通过中间件的CSRF的验证。
1.先了解下两个装饰器
from django.views.decorators.csrf import csrf_exempt, csrf_protect
csrf_exempt 给单个视图排除校验
csrf_protect 给单个视图必须校验
2.简单写一下示例:
settings.py文件
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',
]
urls.py文件
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'login',views.login)
]
views.py文件
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt, csrf_protect
# @csrf_protect # 必须校验csrf_token
# @csrf_exempt # 排除校验csrf_token
def login(request):
return render(request, 'login.html')
html文件
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="content-Type" charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<p>
用户名:<input type="text" name="user">
</p>
<p>
密码:<input type="password" name="pwd">
</p>
<button type="submit">登录</button>
</form>
</body>
</html>
现在 settings 设置的相当于全局的设置,而 @csrf_exempt或者@csrf_protect这两个装饰器是对局部的设置
如果使用csrf_protect,那么html中提交的表单没有csrf_token 就会报错
二 、查看Django源码
1.process_request方法中:
从请求的cookie中获取csrftoken的值 ——》csrf_token ——》request.META['CSRF_COOKIE']
2.process_view方法中:
1. 如果视图函数加上了csrf_exempt的装饰器 不做校验
2. 如果请求方式是'GET', 'HEAD', 'OPTIONS', 'TRACE' 也不做校验
3. 其他的请求方式做校验
request.META.get('CSRF_COOKIE') —— 》 csrf_token # 拿到csrf_token
request_csrf_token = "" # 取值有两种方法
1.
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '') # 从request.POST中获取csrfmiddlewaretoken对应的值
2.
request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '') # 从请求头中获取X-csrftoken 的值
request_csrf_token 和 csrf_token 进行对比校验
如果校验成功 正常走
如果校验不成功 拒绝
来源:oschina
链接:https://my.oschina.net/u/4393789/blog/3790299