CSRF保护
介绍
跨站请求伪造是一种恶意攻击,攻击者利用已认证用户的身份执行未经授权的命令。值得庆幸的是,Laravel 可以轻松保护你的应用程序免受跨站请求伪造(CSRF) 攻击。
漏洞解释
如果您不熟悉跨站请求伪造,让我们讨论一个如何利用此漏洞的示例。假设您的应用程序有一个/user/email
路由,它接受一个POST
更改已验证用户电子邮件地址的请求。最有可能的是,此路由期望一个email
输入字段包含用户想要开始使用的电子邮件地址。
如果没有 CSRF 保护,恶意网站可能会创建一个指向应用程序/user/email
路由的 HTML 表单并提交恶意用户自己的电子邮件地址:
1<form action="https://your-application.com/user/email" method="POST">2 <input type="email" value="malicious-email@example.com">3</form>4 5<script>6 document.forms[0].submit();7</script>
如果恶意网站在页面加载时自动提交表单,恶意用户只需引诱您的应用程序的毫无戒心的用户访问他们的网站,他们的电子邮件地址就会在您的应用程序中被更改。
为了防止此漏洞,我们需要检查每个传入的POST
、、或请求PUT
,以获取恶意应用程序无法访问的秘密会话值。PATCH
DELETE
防止 CSRF 请求
Laravel 会自动为应用程序管理的每个Events用户会话生成一个 CSRF“令牌” 。此令牌用于验证经过身份验证的用户是否是实际向应用程序发出请求的用户。由于此令牌存储在用户会话中,并且每次会话重新生成时都会更改,因此恶意应用程序无法访问它。
可以通过请求的会话或通过csrf_token
辅助函数访问当前会话的 CSRF 令牌:
1use Illuminate\Http\Request;2 3Route::get('/token', function (Request $request) {4 $token = $request->session()->token();5 6 $token = csrf_token();7 8 // ...9});
每当您在应用程序中定义“POST”、“PUT”、“PATCH”或“DELETE”HTML 表单时,都应该_token
在表单中包含一个隐藏的 CSRF 字段,以便 CSRF 防护中间件能够验证请求。为了方便起见,您可以使用@csrf
Blade 指令来生成隐藏的 token 输入字段:
1<form method="POST" action="/profile">2 @csrf3 4 <!-- Equivalent to... -->5 <input type="hidden" name="_token" value="{{ csrf_token() }}" />6</form>
默认包含在中间件组中的中间件将自动验证请求输入中的令牌是否与会话中存储的令牌匹配。当这两个令牌匹配时,我们就知道已通过身份验证的用户是发起请求的用户Illuminate\Foundation\Http\Middleware\ValidateCsrfToken
。web
CSRF 令牌和 SPA
如果您正在构建使用 Laravel 作为 API 后端的 SPA,则应查阅Laravel Sanctum 文档以获取有关使用 API 进行身份验证和防范 CSRF 漏洞的信息。
将 URI 从 CSRF 保护中排除
有时您可能希望将一组 URI 排除在 CSRF 保护之外。例如,如果您使用Stripe处理付款并使用其 Webhook 系统,则需要将 Stripe Webhook 处理程序路由从 CSRF 保护中排除,因为 Stripe 不知道要向您的路由发送哪个 CSRF 令牌。
web
通常,你应该将这些类型的路由放在Laravel 应用于文件中所有路由的中间件组之外。但是,你也可以通过向应用程序文件中的方法routes/web.php
来提供特定路由的 URI 来排除它们:validateCsrfTokens
bootstrap/app.php
1->withMiddleware(function (Middleware $middleware) {2 $middleware->validateCsrfTokens(except: [3 'stripe/*',4 'http://example.com/foo/bar',5 'http://example.com/foo/*',6 ]);7})
为了方便起见,运行测试 时会自动为所有路由禁用 CSRF 中间件。
X-CSRF-TOKEN
除了检查 POST 参数中的 CSRF 令牌之外,默认Illuminate\Foundation\Http\Middleware\ValidateCsrfToken
包含在web
中间件组中的中间件还会检查X-CSRF-TOKEN
请求标头。例如,你可以将令牌存储在 HTMLmeta
标记中:
1<meta name="csrf-token" content="{{ csrf_token() }}">
然后,您可以指示 jQuery 之类的库自动将令牌添加到所有请求标头中。这为使用旧版 JavaScript 技术的基于 AJAX 的应用程序提供了简单、便捷的 CSRF 保护:
1$.ajaxSetup({2 headers: {3 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')4 }5});
X-XSRF-令牌
Laravel 将当前的 CSRF 令牌存储在一个加密的XSRF-TOKEN
Cookie 中,该 Cookie 包含在框架生成的每个响应中。您可以使用 Cookie 值来设置X-XSRF-TOKEN
请求标头。
发送此 cookie 主要是为了方便开发人员,因为某些 JavaScript 框架和库(如 Angular 和 Axios)会自动将其值放在X-XSRF-TOKEN
同源请求的标头中。
默认情况下,该resources/js/bootstrap.js
文件包含 Axios HTTP 库,它将自动X-XSRF-TOKEN
为您发送标头。