python之csrf简介
django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。
全局:
中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
注意:from django.views.decorators.csrf import csrf_exempt,csrf_protect
原理
当用post提交数据的时候,django会去检查是否有一个csrf的随机字符串,如果没有就会报错,这也是之前我们一直将其注释的原因,错误如下:
在django内部支持生成这个随机字符串
通过form提交
在form表单里面需要添加{%csrf_token%}
这样当你查看页面源码的时候,可以看到form中有一个input是隐藏的
总结原理:当用户访问login页面的时候,会生成一个csrf的随机字符串,,并且cookie中也存放了这个随机字符串,当用户再次提交数据的时候会带着这个随机字符串提交,如果没有这个随机字符串则无法提交成功
cookie中存放的csrftoken如下图
通过ajax提交
因为cookie中同样存在csrftoken,所以可以在js中通过:
$.cooke("cstftoken")获取
如果通过ajax进行提交数据,这里提交的csrftoken是通过请求头中存放,需要提交一个字典类型的数据,即这个时候需要一个key。
在views中的login函数中:from django.conf import settings,然后打印print(settings.CSRF_HEADER_NAME)
这里需要注意一个问题,这里导入的settings并不是我们在项目文件下看到的settings.py文件,这里是是一个全局的settings配置,而当我们在项目目录下的settings.py中配置的时候,我们添加的配置则会覆盖全局settings中的配置
print(settings.CSRF_HEADER_NAME)打印的内容为:HTTP_X_CSRFTOKEN
这里的HTTP_X_CSRFTOKEN是django在X_CSRF的前面添加了HTTP_,所以实际传递的是就是X_CSRFtoken,而在前端页面的ajax传递的时候由于不能使用下划线所以传递的是X_CSRFtoken
下面是在前端ajax中写的具体内容:
$("#btn1").click(function () {
$.ajax({
url:"/login/",
type:"POST",
data:{"usr":"root","pwd":"123"},
headers:{ "X-CSRFtoken":$.cookie("csrftoken")},
success:function (arg) { }
})
})
但是如果页面中有多个ajax请求的话就在每个ajax中添加headers信息,所以可以通过下面方式在所有的ajax中都添加
$.ajaxSetup({
beforeSend:function (xhr,settings) {
xhr.setRequestHeader("X-CSRFtoken",$.cookie("csrftoken"))
}
});
这样就会在提交ajax之前执行这个方法,从而在所有的ajax里都加上这个csrftoken
这里的xhr是XMLHttpRequest的简写,ajax调用的就是这个方法
如果想要实现在当get方式的时候不需要提交csrftoken,当post的时候需要,实现这种效果的代码如下:
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);
}
}
});
这样就实现了当GET|HEAD|OPTIONS|TRACE这些方式请求的时候不需要提交csrftoken
最新文章
- AC日记——二叉堆练习3 codevs 3110
- 创建ACCESS数据库,并且创建表和数据。重点:关闭ACCESS数据库引用
- Ubuntu 14.4 下安装 Tomcat + Solr5.2
- Spring并发访问的线程安全性问题
- XAML基础
- 运行时修改TimerTask的执行周期
- JMS开发(三):JMS消息的确认方式
- sre_constants.error: unbalanced parenthesis
- Linux Bash环境下单引(')、双引号(";)、反引号(`)、反斜杠(\)的小结
- 2016最新Java笔试题集锦
- PageRank在Hadoop和spark下的实现以及对比
- 网站地图怎么做?dedecms网站地图制作方法听语音
- Windows Server2012 故障转移集群之动态仲裁(Dynamic Quorum)
- C - Heavy Transportation &;&; B - Frogger(迪杰斯变形)
- 干货!最全羽毛球技术动态分解gif图
- Django 学习第二天——URL路由及模板渲染方式
- redis的键命令
- H5视频推流方案
- 转:解决windows下eclipse中android项目关联android library project失败问题
- Unity使用C#实现简单Scoket连接及服务端与客户端通讯
热门文章
- SourceTreet提交时显示remote: Incorrect username or password ( access token )(4种解决办法)
- Solon 的 PathVariable 不需注解
- Tun/Tap接口使用指导
- UML活动图(Activity Diagram)
- java泛型笔记
- Spring配置文件中bean标签中init-method和destroy-method和用注解方式配置
- Antd cracoTs Js 配置流程
- linux 解压与压缩
- ElementUI 不维护了?供我们选择的 Vue 组件库还有很多!
- 区块链入门到实战(18)之以太坊(Ethereum) – 什么是智能合约