在header中添加自定义属性防止CSRF
来源:互联网 发布:查看java进程 编辑:程序博客网 时间:2024/06/05 18:19
在header中添加自定义属性防止CSRF
一、 概述
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账等造成的问题包括:个人隐私泄露以及财产安全。
二、目前行业常见的防御方式
1.验证Referer;
2.使用验证码,用户体验比较差;
3.使用CSRF token,又分为在form表单中添加隐藏域携带token和在header中添加自定义参数携带token;
4.在请求地址中添加token并验证。
三、具体实现步骤
本文对于二中第3种方式的在请求header中添加自定义参数进行csrf参数进行防御进行实战介绍,该方式适合使用ajax异步提交表单和请求时使用。
1)在服务端做全局的token生成,token为一次性令牌(one-time token)令牌周期依赖于session的生命周期
示例:
$csrf_token = md5(uniqid(rand(), TRUE)); $_SESSION['csrf_token_name'] = $csrf_token;
2) 在前端得到token值
<form method="POST" action='target.php'>money:<input type='text' name='money'><input type='hidden' name='csrf_token_name' value="<?=$_SESSION['csrf_token_name'];?>">bank:<input type='text' name='toBankId'><input type='submit' name='submit' value='submit'> </form>
为了书写方便,可以将<input type='hidden' name='csrf_token_name' value="<?=$_SESSION['csrf_token_name'];?>">
封装成一个方法,前端页面直接调用即可。
3)ajax提交表单数据
改写jQuery中以下部分
if ( s.crossDomain == null ) { parts = rurl.exec( s.url.toLowerCase() ); s.crossDomain = !!( parts && ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] || ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) ); } // Convert data if not already a string if ( s.data && s.processData && typeof s.data !== "string" ) { if(s.type.toUpperCase()=="POST"){ if(s.data && s.data['csrf_token_name'] != undefined){ s.headers = s.headers || {}, s.headers['Csrf-Token-Name'] = s.data['csrf_token_name']; delete s.data['csrf_token_name']; } } s.data = jQuery.param( s.data, s.traditional ); }
这样可以全局获取token并且将token附在header中Csrf-Token-Name上,提交至服务端。
4)服务端进行验证
if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST') { return true; } if($this->is_need_check_csrf()==false){ return true; } $session_hash = $_SESSION['csrf_token_name']; $request_method = 2; if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') { $request_method = 1; $_scrf_key = "HTTP_Csrf_Token_Name"; $valid = isset($_SERVER[$_scrf_key], $session_hash) && hash_equals($_SERVER[$_scrf_key],$session_hash); } else { $valid = isset($_POST['csrf_token_name'], $session_hash) && hash_equals($_POST['csrf_token_name'], $session_hash);unset($_POST['csrf_token_name']); } csrf_regenerate(); if ($valid !== TRUE) { if($request_method == 1){ echo json_encode(array("statusCode"=>500,"errors"=>"页面停留时间过长,请刷新页面")); exit; }else if($request_method ==2){ if(isset($_SERVER['HTTP_REFERER'])){ $referer=$_SERVER['HTTP_REFERER']; header("Location: $referer"); exit; }else{ header("Location: /"); exit; } } }
验证请求是否合法,对于ajax请求返回json数据。
5)前端接收后端返回数据
如果请求验证通过,进行后续的业务处理,如果验证不通过,返回500状态码,前端页面进行刷新操作,提示停留时间过长造成的(可能的原因是长时间没操作,session过期,或者同一个页面多次打开,该token值已被其他tab使用过了),此时系统自动刷新当前页面。对于请求验证通过,但是页面不成功的情况,需要用户再次进行操作,此时需要请求回带新的token(x_token)回来。
// If not modified if ( status === 304 ) { statusText = "notmodified"; isSuccess = true; // If we have data } else { try { success = ajaxConvert( s, response ); statusText = "success"; isSuccess = true; } catch(e) { // We have a parsererror statusText = "parsererror"; error = e; } } var t = JSON.stringify(response); if(t && t.statusCode != undefined && t.statusCode!=200 && t.data!=undefined && t.data.x_token != undefined){ $("input[name=csrf_token_name]").val(t.data.x_token); } if(t && t.statusCode != undefined && t.statusCode == 500){ setTimeout(function() { location.reload(); }, 1000); }
- 在header中添加自定义属性防止CSRF
- 在jquery的ajax中添加自定义的header信息
- Jquery中添加自定义Header
- 在header中添加LOGO
- MVC中防止CSRF攻击
- 在VS2008中创建自定义控件(九)添加属性
- 在 K3 系统中,为物料添加自定义属性。
- 在easyui树节点中添加自定义属性
- 如何在Xib中添加自定义的属性?
- nginx添加自定义header
- php中如何防止CSRF攻击
- Nginx添加header防止网页被iframe
- 在VS2008中创建自定义控件(十一)添加在属性窗口中可折叠的属性(一)
- 在VS2008中创建自定义控件(十二)添加在属性窗口中可折叠的属性(二)
- 在VS2008中创建自定义控件(十一)添加在属性窗口中可折叠的属性(一)
- 在VS2008中创建自定义控件(十二)添加在属性窗口中可折叠的属性(二)
- 在gridview的header中添加新行
- [转]怎样在UICollectionView中添加Header和footer
- linux堆内存漏洞利用之fastbin
- 给出一个百分制成绩,要求输出成绩等级A,B,C,D,E。90分以上为A,80~89分为B,70~79分为C,60~69分为D,60分以下为E
- HDOJ1022
- 1012. 数字分类 (20)
- macOS gdb: please check gdb is codesigned
- 在header中添加自定义属性防止CSRF
- Verilog中inout的用法(二)
- 笔试面试常考的一些小知识
- 程序员从打字开始
- 蘑菇街-应用平台开发工程师笔试编程题
- 课堂练习1(第四周)
- java自学笔记——枚举类
- ELF与链接
- shell正则表达式