防攻击(CSRF)
作者:@skyflask
转载本文请注明出处:https://www.cnblogs.com/skyflask/articles/9833607.html
目录
CSRF定义
CSRF解决
1、原理
2、form方式提交
3、Ajax方式提交
4、全局和局部应用
5、总结
CSRF定义
CSRF(Cross-site request forgery)跨站请求伪造,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。通过伪装来自受信任用户的请求来利用受信任的网站。
CSRF的防护通常有两种方式,一个是通过Challenge-Response的方式,例如通过Captcha和重新输入密码等方式来验证请求是否伪造,但这会影响用户体验,类似银行付款会采用这样的方式。另一种是通过随机Token的方式,多数Web系统都会采用这种方式,Django也是用的这种。
在Django中,我们form提交表单时,如果setttings里面使用的是默认配置,则会默认启用csrf:
1 2 3 4 5 6 7 8 9 10 11 | 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' , 'middle.md1.MD1' , 'middle.md1.MD2' , ] |
对于新手而言,我们常用的方式就是注释掉django.middleware.csrf.CsrfViewMiddleware。
CSRF解决
1、原理
客户端get请求时,django会生成随机字符串给客户,暂存在客户端,当客户端提交form表单的时候,服务端会检查这个随机字符串,如果没有随机字符串,则django不允许通过,报403错误。其实,CSRF就是Django中的一个中间介。
2、form方式提交
在form表单里面我们通过通过添加{%csrf_token%}这个tag来解决。这样当你查看页面源码的时候,可以看到form中有一个input是隐藏的:
总结原理:当用户访问login页面的时候,会生成一个csrf的随机字符串,,并且cookie中也存放了这个随机字符串,当用户再次提交数据的时候会带着这个随机字符串提交,如果没有这个随机字符串则无法提交成功
3、Ajax方式提交
因为cookie中同样存在csrftoken,所以可以在js中通过$.cooke("cstftoken")获取,注意:这里需要导入jquery.cookie.js文件。
如果通过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中写的具体内容:
1 2 3 4 5 6 7 8 9 10 11 | $( "#btn1" ).click(function () { $.ajax({ url: "/login/" , type : "POST" , data:{ "username" : "root" , "pwd" : "123456" }, headers:{ "X-CSRFtoken" :$.cookie( "csrftoken" )}, success:function (arg) { } }) }) |
但是如果页面中有多个ajax请求的话就在每个ajax中添加headers信息,所以可以通过下面方式在所有的ajax中都添加
1 2 3 4 5 | $.ajaxSetup({ beforeSend:function (xhr,settings) { xhr.setRequestHeader( "X-CSRFtoken" ,$.cookie( "csrftoken" )) } }); |
这样就会在提交ajax之前执行这个方法,从而在所有的ajax里都加上这个csrftoken,这里的xhr是XMLHttpRequest的简写,ajax调用的就是这个方法。
如果想要实现在当get方式的时候不需要提交csrftoken,当post的时候需要,实现这种效果的代码如下:
1 2 3 4 5 6 7 8 9 10 11 | function csrfSafeMethod(method) { / / 以下方法不需要实行CSRF保护机制 return ( / ^(GET|HEAD|OPTIONS|TRACE)$ / .test(method)); } $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings. type ) && !this.crossDomain) { xhr.setRequestHeader( "X-CSRFToken" , csrftoken); } } }); |
4、全局和局部应用
settings里面,允许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
对于ajax中,采用ajaxSetup方式也是全局都加,比如get方式是不需要的,可以如下配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | var csrftoken = $.cookie( 'csrftoken' ); function csrfSafeMethod(method) { / / these HTTP methods do not require CSRF protection return ( / ^(GET|HEAD|OPTIONS|TRACE)$ / .test(method)); } $.ajaxSetup({ beforeSend: function(xhr, settings) { / / settings 会获取到ajax里面的所有配置 if (!csrfSafeMethod(settings. type ) && !this.crossDomain) { xhr.setRequestHeader( "X-CSRFToken" , csrftoken); } } }); function Do(){ $.ajax({ url: "/app01/test/" , data:{ id : 1 }, type : 'POST' , success:function(data){ console.log(data); } }); } |
5、总结
- csrf在ajax提交的时候通过请求头传递的给后台的
- csrf在前端的key为:X-CSRFtoken,到后端的时候django会自动添加HTTP_,并且最后为HTTP_X_CSRFtoken
- csrf在form中提交的时需要在前端form中添加{%csrftoken%}
- csrf可以全局设置和局部设置,局部设置又可以分:指定views函数执行或不执行csrf保护。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」