Laravel框架为用户项目的安全性做了充分的考虑,不仅在用户认证上提供了方便的auth guard,针对经常被挖掘的CSRF漏洞,laravel在请求认证方面,也提供了严格的CSRF Token机制,以验证登录用户和发起请求者是否是同一人,如果不是则请求失败。
不过优秀的安全性也会经常为新手带来困扰,以前使用的Ajax突然报错,或者简单的表单POST请求无法提交。老九从个人笔记和网上总结了一些常见问题的解决方案如下:
1. Laravel ajax请求 419错误
错误解决办法在页面上添加
<meta name="csrf-token" content="{{ csrf_token() }}">
然后在页面的script标签中添加
$.ajaxSetup({headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}});
2. post提交数据时候显示如下:The page has expired due to inactivity. Please refresh and try again
这是由于在laravel框架中有此要求:任何指向 web 中 POST, PUT 或 DELETE 路由的 HTML 表单请求都应该包含一个 CSRF 令牌,否则,这个请求将会被拒绝。
在表单内添加语句{{ csrf_field() }}即可。
3. 通用方法:
Laravel提供了一个全局帮助函数csrf_token来获取该Token值,因此只需在视提交图表单中添加如下HTML代码即可在请求中带上Token:
<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
该段代码等同于全局帮助函数csrf_field的输出:
<?php echo csrf_field(); ?>
在Blade模板引擎中还可以使用如下方式调用:
{!! csrf_field() !!}
如果使用Ajax提交POST表单,又该如何处理呢?我们可以将Token设置在meta中:
<meta name="csrf-token" content="{{ csrf_token() }}">
然后在全局Ajax中使用这种方式设置X-CSRF-Token请求头并提交:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Laravel的VerifyCsrfToken中间件会检查X-CSRF-TOKEN请求头,如果该值和Session中CSRF值相等则验证通过,否则不通过。
4. 静态页面或者不需要验证的环境如何解决POST请求无法提交的问题
有的时候我们需要静态页面来提供请求,这涉及一些需要CDN的环境。另外并不是所有请求都需要避免CSRF攻击,比如去第三方API获取数据的请求。
可以通过在VerifyCsrfToken(app/Http/Middleware/VerifyCsrfToken.php)中间件中将要排除的请求URL添加到$except属性数组中:
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier
{
/**
* 指定从 CSRF 验证中排除的URL
*
* @var array
*/
protected $except = [
'testCsrf'
];
}