Django中间件之csrf_token
一 、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 进行对比校验
如果校验成功 正常走
如果校验不成功 拒绝

浙公网安备 33010602011771号