python框架之Django(9)-CSRF
准备
现有如下模板和视图:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="/login/" method="post">
<p>用户名:<input type="text" name="username"></p>
<p>密码:<input type="text" name="password"></p>
<p><input type="submit" value="提交"></p>
<p style="color: red"> {{ msg }}</p>
</form>
</body>
</html>
login.html
from django.shortcuts import render,HttpResponse def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
print(username, password)
return HttpResponse('登陆成功')
else:
return render(request, 'login.html')
views.py
使用
表单提交
使用上述模板中表单直接进行提交时,会发现会返回403错误如下:

这是因为Django中默认配置了一个拦截CSRF请求的中间件,在settings.py中可配置:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', # 此项便是拦截CSRF请求的中间件
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
settings.py
- 方案一:去除该中间件(不推荐)- 直接注释该行即可。 - MIDDLEWARE = [ 
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 # 'django.middleware.csrf.CsrfViewMiddleware', # 此项便是拦截CSRF请求的中间件
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 ]- setting.py - 注释之后就可以正常提交请求了。 
- 方案二:表单中添加csrf_token- <!DOCTYPE html> 
 <html lang="en">
 <head>
 <meta charset="UTF-8">
 <title>登录</title>
 </head>
 <body>
 <form action="/login/" method="post">
 {% csrf_token %}
 <p>用户名:<input type="text" name="username"></p>
 <p>密码:<input type="text" name="password"></p>
 <p><input type="submit" value="提交"></p>
 <p style="color: red"> {{ msg }}</p>
 </form>
 </body>
 </html>- login.html - 在表单中添加上‘{%csrf_token%}’之后,查看网页源代码会发现表单中多了一个隐藏的输入框,如下:  - Django通过这种方式让表单的请求带着token一起发送到服务器去验证。 
Ajax请求
修改login.html内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
<script src="/static/jquery.min.js"></script>
</head>
<body>
<script>
function login() {
$.ajax({
url: "/login/",
type: "POST",
data: {"usr": "admin", "pwd": "123"},
{#headers:{ "X-CSRFtoken":$.cookie("csrftoken")},#}
success: function (data) {
alert(data)
}
})
}
login()
</script>
</body>
</html>
login.html
访问该页面会发现与表单请求一样被拦截:
- 方案一:headers中携带csrf_token- <!DOCTYPE html> 
 <html lang="en">
 <head>
 <meta charset="UTF-8">
 <title>登录</title>
 <script src="/static/jquery.min.js"></script>
 </head>
 <body>
 <script>
 function login() {
 $.ajax({
 url: "/login/",
 type: "POST",
 data: {"usr": "admin", "pwd": "123"},
 headers: {
 "X-CSRFtoken": '{{csrf_token}}'
 },
 success: function (data) {
 alert(data)
 }
 })
 }
 login()
 </script>
 </body>
 </html>- login.html 
- 方案二:data中携带csrf_token- <!DOCTYPE html> 
 <html lang="en">
 <head>
 <meta charset="UTF-8">
 <title>登录</title>
 <script src="/static/jquery.min.js"></script>
 </head>
 <body>
 {% csrf_token %}
 <script>
 function login() {
 $.ajax({
 url: "/login/",
 type: "POST",
 data: {"usr": "admin", "pwd": "123", "csrfmiddlewaretoken": '{{csrf_token}}'},
 success: function (data) {
 alert(data)
 }
 })
 } login()
 </script>
 </body>
 </html>- login.html 
补充
全局添加csrf_token
如果页面中有多个ajax请求的话就可以通过下面方式在所有的ajax中添加headers信息:
$.ajaxSetup({
        beforeSend: function (xhr, settings) {
            xhr.setRequestHeader("X-CSRFtoken", '{{csrf_token}}')
        }
    });
这样就会在提交ajax之前执行这个方法,从而在所有的ajax里都加上这个csrftoken。
仅post提交添加csrf_token
如果想要实现在当get方式的时候不需要提交csrftoken,当post的时候需要,实现这种效果的代码如下:
function csrfSafeMethod(method) {
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    beforeSend: function (xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", '{{ csrf_token }}');
        }
    }
});
上述示例因csrf_token都是通过模板语言取出,所以html页必须由django的render函数渲染过。同理也可通过js取出cookie中csrf_token值,填充到对应位置即可。
指定视图函数不校验csrf
from django.views.decorators.csrf import csrf_exempt @csrf_exempt
def view_func(request):
pass
python框架之Django(9)-CSRF的更多相关文章
- python框架之django
		python框架之django 本节内容 web框架 mvc和mtv模式 django流程和命令 django URL django views django temple django models ... 
- 第六篇:web之python框架之django
		python框架之django python框架之django 本节内容 web框架 mvc和mtv模式 django流程和命令 django URL django views django te ... 
- Python框架之Django学习
		当前标签: Django Python框架之Django学习笔记(十四) 尛鱼 2014-10-12 13:55 阅读:173 评论:0 Python框架之Django学习笔记(十三) 尛 ... 
- Python框架之Django的相册组件
		Python框架之Django的相册组件 恩,没错,又是Django,虽然学习笔记已经结贴,但是学习笔记里都是基础的,Django的东西不管怎么说还是很多的,要学习的东西自然不会仅仅用十几篇博文就能学 ... 
- Python高级进阶(二)Python框架之Django写图书管理系统(LMS)
		正式写项目准备前的工作 Django是一个Web框架,我们使用它就是因为它能够把前后端解耦合而且能够与数据库建立ORM,这样,一个Python开发工程师只需要干自己开发的事情就可以了,而在使用之前就我 ... 
- Python自动化之Django的CSRF
		什么CSRF? CSRF, Cross Site Request Forgery, 跨站点伪造请求.举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果 某个用户已经登录到你的网站上了,那么当这个 ... 
- python框架之Django(11)-中间件
		介绍 在django中,中间件其实就是一个类,在一个请求到来和这个请求结束之前,django会根据自己的规则在合适的时机执行中间件中相应的方法. 在django项目的settings模块中,有一个 M ... 
- Python框架之Django学习笔记(十一)
		话说上次说到数据库的基本访问,而数据库我们主要进行的操作就是CRUD,也即是做计算处理时的增加(Create).读取(Retrieve)(重新得到数据).更新(Update)和删除(Delete),俗 ... 
- Python框架之Django学习笔记(十二)
		Django站点管理 十一转眼结束,说好的充电没能顺利开展,反而悠闲的看了电视剧以及去影院看了新上映的<心花路放>.<亲爱的>以及<黄金时代>,说好的劳逸结合现在回 ... 
随机推荐
- grokking deep learning
			https://www.manning.com/books/grokking-deep-learning?a_aid=grokkingdl&a_bid=32715258 
- tensorflow 笔记13:了解机器翻译,google NMT,Attention
			一.关于Attention,关于NMT 未完待续... 以google 的 nmt 代码引入 探讨下端到端: 项目地址:https://github.com/tensorflow/nmt 机器翻译算是 ... 
- ios调试-查看日志
			连上mac,然后打开“console.app”, 左侧设备里选这个设备. 
- iScroll的使用
			CDN: <script src="//ossweb-img.qq.com/images/js/iscroll_library/iscroll-5.2.0.js">&l ... 
- 【Log】SLF4J简单入门
			SLF4J介绍 SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统.按照官方的说法,SLF4J是一个用于日 ... 
- iOS开发下载文件速度计算
			当我们写下载界面的时候,需要向用户展示每秒下载多少KB,这个时候就需要计算速度.如下: 我用的是AFNetworking来做下载的,我们拿AFHTTPRequestOperation来举列,AFHTT ... 
- 微信小程序——动态设置swiper的高度
			根据小程序的设定,swiper组件默认高度为150px,无法根据内容来撑高.如果里面的内容固定还好说,直接设置一个高度就可以了.要是里面内容是动态变化的,这个特性使得我们使用这个组件的时候感到诸多不便 ... 
- C#访问gsoap的服务--可用
			问题来源: C++开发一个webservice,然后C#开发客户端,这样就需要C#的客户端访问gsoap的服务端.(大家都知道gsoap是C/C++开发webservice的最佳利器) 为什么不考虑直 ... 
- 并发编程基础之volatile关键字的用法
			一:概念 volatile关键字是一个轻量级的线程同步,它可以保证线程之间对于共享变量的同步,假设有两个线程a和b, 它们都可以访问一个成员变量,当a修改成员变量的值的时候,要保证b也能够取得成员变量 ... 
- iOS - 解决 Cocoapods 第三方库下载不下来
			Cocoapods 第三方库下载不下来问题:一些第三方的库由于网的原因下载不下里 (解决思路:(原理) cocoapods 下载的时候 会先从缓存中拿 缓存中没有再去下载 所以可以把下载不下来的放到缓 ... 
