CSRF 保护
CSRF 保护#
简介#
跨站点请求伪造是一种恶意利用,利用这种手段,代表经过身份验证的用户执行未经授权的命令。值得庆幸的是,Laravel 可以轻松保护您的应用程序免受 跨站点请求伪造 (CSRF)攻击。
漏洞的解释#
如果您不熟悉跨站点请求伪造,让我们讨论一个如何利用此漏洞的示例。假设您的应用程序具有一个 /user/email
接受 POST
更改身份验证用户的电子邮件地址的请求的路由。最有可能的是,此路由希望 email
输入字段包含用户希望开始使用的电子邮件地址。
没有 CSRF 保护,恶意网站可能会创建指向您的应用程序 /user/email
路由的 HTML 表单,并提交恶意用户自己的电子邮件地址:
<form action="https://your-application.com/user/email" method="POST">
<input type="email" value="malicious-email@example.com">
</form>
<script>
document.forms[0].submit();
</script>
如果恶意网站在页面加载时自动提交了表单,则恶意用户只需要诱使您的应用程序的一个毫无戒心的用户访问他们的网站,他们的电子邮件地址就会在您的应用程序中更改。
为了防止这种漏洞,我们需要检查每一个传入的 POST
, PUT
, PATCH
或 DELETE
为秘密会话值恶意的应用程序无法访问请求。
阻止 CSRF 请求#
Laravel 为应用程序管理的每个活动 用户会话 自动生成 CSRF 「令牌」。此令牌用于验证经过身份验证的用户是实际向应用程序发出请求的人。由于此令牌存储在用户的会话中,并且每次重新生成会话时都会更改,因此恶意应用程序将无法访问它。
当前会话的 CSRF 令牌可以通过请求的会话或通过 csrf_token
辅助函数进行访问:
use Illuminate\Http\Request;
Route::get('/token', function (Request $request) {
$token = $request->session()->token();
$token = csrf_token();
// ...
});
每当您在应用程序中定义 HTML 表单时,都应在表单中包含一个隐藏的 CSRF _token
字段,以便 CSRF 保护中间件可以验证请求。为了方便起见,您可以使用 @csrf
Blade 指令生成隐藏的令牌输入字段:
<form method="POST" action="/profile">
@csrf
<!-- 等同于 -->
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
</form>
App\Http\Middleware\VerifyCsrfToken
中间件,其包括在在 web
由默认中间件基,将自动验证在请求输入的令牌匹配令牌存储在会话。当这两个令牌匹配时,我们知道经过身份验证的用户就是发起请求的用户。
CSRF Tokens & SPAs#
如果要构建将 Laravel 用作 API 后端的 SPA Laravel Sanctum 文档 ,以获取有关使用 API 进行身份验证和防范 CSRF 漏洞的信息。
白名单#
有时候你可能希望设置一组不需要 CSRF 保护的 URL 。例如,如果你正在使用 Stripe 处理付款并使用了他们的 webhook 系统,你会需要从 CSRF 的保护中排除 Stripe webhook 处理程序路由,因为 Stripe 不知道要发送什么样的 CSRF 令牌到你的路由。
通常,你应该把这类路由放在 web
中间件组之外,因为 routes/web.php
文件中的 App\Providers\RouteServiceProvider
适用于所有路由。不过,你也可以通过将这类 URL 添加到 VerifyCsrfToken
中间件的 $except
属性中来排除对这类路由的 CSRF 保护:
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* 从 CSRF 验证中排除的 URI
*
* @var array
*/
protected $except = [
'stripe/*',
'http://example.com/foo/bar',
'http://example.com/foo/*',
];
}
技巧:为了方便,当 运行测试 时,所有路由的 CSRF 中间件都会自动禁用。
X-CSRF-TOKEN#
除了检查 POST 参数中的 CSRF 令牌外,App\Http\Middleware\VerifyCsrfToken
中间件还将检查 X-CSRF-TOKEN
请求头。你应该将令牌存储在 HTML meta
标签中:
<meta name="csrf-token" content="{{ csrf_token() }}">
然后,你可以指示类似 jQuery 的库将令牌自动添加到所有请求标头中。这可以为基于 AJAX 的应用程序提供简单、便捷的 CSRF 保护:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
X-XSRF-TOKEN#
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
标头。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: