laravel的CSRF保护
跨站请求伪造(CSRF)是一种通过伪装授权用户的请求来攻击授信网站的恶意漏洞。
Laravel 默认情况下,为了安全考虑,Laravel 期望所有路由都是「只读」操作的(对应请求方式是 GET、HEAD、OPTIONS),如果路由执行的是「写入」操作(对应请求方式是 POST、PUT、PATCH、DELETE),则需要传入一个隐藏的 Token 字段_token
以避免[跨站请求伪造攻击](CSRF)。如果请求方式是 DELETE,但是并没有传递 _token
字段,所以会出现异常。
避免跨站请求伪造攻击的措施就是对写入操作采用非 GET 方式请求,同时在请求数据中添加校验 Token 字段,Laravel 也是这么做的,这个 Token 值会在渲染表单页面时通过 Session 生成,然后传入页面,在每次提交表单时带上这个 Token 值即可实现安全写入,因为第三方站点是不可能拿到这个 Token 值的,所以由第三方站点提交的请求会被拒绝,从而避免 CSRF 攻击。
X-CSRF-Token
除了将 CSRF 令牌作为 POST 参数进行验证外,还可以通过设置 X-CSRF-Token 请求头来实现验证,VerifyCsrfToken 中间件会检查 X-CSRF-TOKEN 请求头。实现方式如下,首先创建一个 meta 标签并将令牌保存到该 meta 标签:1
<meta name="csrf-token" content="{{ csrf_token() }}">
禁止CSRF功能
Laravel默认是开启了,需要关闭此功能有两种方法:
方法一
打开文件:app\Http\Kernel.php
把这行注释掉:1
'App\Http\Middleware\VerifyCsrfToken'
方法二
打开文件:app\Http\Middleware\VerifyCsrfToken.php
修改为: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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42namespace App\Http\Middleware;
// 引入这个
use Closure;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
// 加入这个方法
public function handle($request, Closure $next)
{
// 使用CSRF
//return parent::handle($request, $next);
// 禁用CSRF
return $next($request);
}
// 也可以对指定的表单提交方式使用CSRF
// 只对GET的方式提交使用CSRF,对POST方式提交表单禁用CSRF
public function handle($request, Closure $next)
{
// Add this:
if($request->method() == 'POST')
{
return $next($request);
}
if ($request->method() == 'GET' || $this->tokensMatch($request))
{
return $next($request);
}
throw new TokenMismatchException;
}
}
使用 CSRF
方法一:HTML的代码中加入:1
2
3
4
5
6
7<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<!-- 或者可以使用 Blade 指令 @csrf -->
<form method="POST" action="/profile">
@csrf
...
</form>
另一种是使用cookie方式。
使用cookie方式,需要把app\Http\Middleware\VerifyCsrfToken.php修改为:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20namespace App\Http\Middleware;
use Closure;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return parent::addCookieToResponse($request, $next($request));
}
}