CSRF跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
原理:Laravel为每个用户session生成了一个CSRGToken,该token用来验证登录用户和请求发起者是否是同一人,如果不是则请求失败。
一:CSRF验证
路由部分:
//CSRF
Route::group(['prefix'=>'Home/test'], function () {
Route::match(['get'],'csrf1', 'Home\IndexController@csrf1');
Route::match(['post'],'csrf2', 'Home\IndexController@csrf2') -> name('csrf2');
});
Controller写法:
//csrf1展示表单
public function csrf1(){
return view('Home/test/csrf1');
}
//csrf2处理请求
public function csrf2(){
return '提交成功';
}
视图写法:
\resources\views\Home\test\csrf1.blade.php
<form action="{{route('csrf2')}}" method="post">
姓名:<input type="text" name="name" value="">
<input type="submit" name="">
</form>
浏览器访问:
但是这样提交表单是会失败的,因为我们没有携带token
解决:
在表单中添加一个value为<?php echo csrf_token();?>的input,当然,在blade模板引擎中可以用{{}}简写
<form action="{{route('csrf2')}}" method="post">
姓名:<input type="text" name="name" value="">
<input type="hidden" name="_token" value="{{csrf_token()}}">
<input type="submit" name="">
</form>
重新提交:
同样的,上面的
<input type="hidden" name="_token" value="{{csrf_token()}}">
还可以继续简写,用一个函数来代替,当然这种方法没法做异步
<form action="{{route('csrf2')}}" method="post">
姓名:<input type="text" name="name" value="">
{{csrf_field()}}
<input type="submit" name="">
</form>
二:CSRF排除例外路由
可以到\app\Http\Middleware\VerifyCsrfToken.php中的$except属性数组中设置白名单,这样就能关闭指定对象的CSRF验证
填写白名单:
视图:
<form action="{{route('csrf2')}}" method="post">
姓名:<input type="text" name="name" value="">
<input type="submit" name="">
</form>
浏览器访问:
同时定义多规则时需要,分隔
设置全部忽略只需要填*即可
protected $except = [
//排除所有CSRF验证
'*'
];
}