CSRF 保护

未匹配的标注
本文档最新版为 11.x,旧版本可能放弃维护,推荐阅读最新版!

CSRF 防护

简介

跨站请求伪造(CSRF)是一种恶意攻击手段,攻击者利用已认证用户的身份执行未授权的操作。幸运的是,Laravel 提供了简单有效的方式来防护您的应用免受 跨站请求伪造 攻击。

漏洞原理说明

假设您不熟悉 CSRF 攻击,我们通过一个例子说明这种漏洞如何被利用。假设您的应用有一个 /user/email 路由,通过 POST 请求来修改认证用户的邮箱地址。这个路由通常需要接收一个包含新邮箱地址的 email 字段。

在没有 CSRF 防护的情况下,恶意网站可以创建一个表单,指向您应用的 /user/email 路由,并提交攻击者的邮箱地址:

<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>

如果恶意网站在页面加载时自动提交这个表单,攻击者只需要诱骗您的应用用户访问该网站,就能在您的应用中修改用户邮箱地址。

为了防止这种漏洞,我们需要检查每个传入的 POSTPUTPATCHDELETE 请求,验证是否包含恶意应用无法获取的会话密钥。

阻止 CSRF 请求

Laravel 会自动为应用程序管理的每个活动 用户会话 生成一个 CSRF 「令牌」。此令牌用于验证经过身份验证的用户是否是实际向应用程序发出请求的人。由于此令牌存储在用户的会话中,并且每次重新生成会话时都会发生变化,因此恶意应用程序无法访问它。

当前会话的 CSRF 令牌可以通过请求的会话或 csrf_token 辅助函数来访问:

use Illuminate\Http\Request;

Route::get('/token', function (Request $request) {
    $token = $request->session()->token();

    $token = csrf_token();

    // ...
});

每当你在应用程序中定义 POSTPUTPATCHDELETE HTML 表单时,都应该在表单中包含一个隐藏的 CSRF _token 字段,以便 CSRF 保护中间件可以验证请求。为了方便起见,你可以使用 @csrf Blade 指令来生成隐藏令牌输入字段:

<form method="POST" action="/profile">
    @csrf

    <!-- Equivalent to... -->
    <input type="hidden" name="_token" value="{{ csrf_token() }}" />
</form>

默认情况下包含在 web 中间件组中的 Illuminate\Foundation\Http\Middleware\ValidateCsrfToken 中间件 将自动验证请求输入中的令牌是否与会话中存储的令牌匹配。当这两个令牌匹配时,我们就知道经过身份验证的用户是发起请求的用户。

CSRF Tokens & SPAs

如果你正在构建使用 Laravel 作为 API 后端的 SPA,则应查阅 Laravel Sanctum 文档,了解有关使用 API 进行身份验证和防范 CSRF 漏洞的信息。

从 CSRF 保护中排除 URI

有时您可能希望从 CSRF 保护中排除一组 URI。例如,如果您使用 Stripe 处理支付并利用他们的 webhook 系统,您将需要从 CSRF 保护中排除您的 Stripe webhook 处理程序路由,因为 Stripe 不知道要发送到您的路由的 CSRF 令牌。

通常,您应该将这些类型的路由放在 Laravel 在 routes/web.php 文件中应用于所有路由的 web 中间件组之外。但是,您也可以通过在应用程序的 bootstrap/app.php 文件中将其 URI 提供给 validateCsrfTokens 方法来排除特定路由:

->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: [
        'stripe/*',
        'http://example.com/foo/bar',
        'http://example.com/foo/*',
    ]);
})

[!NOTE]
为了方便,CSRF 中间件在运行测试时会自动为所有路由禁用, 试运行

X-CSRF-TOKEN

除了检查作为 POST 参数的 CSRF 令牌外,默认包含在 web 中间件组中的 Illuminate\Foundation\Http\Middleware\ValidateCsrfToken 中间件还将检查 X-CSRF-TOKEN 请求头。您可以,例如,将令牌存储在 HTML meta 标签中:

<meta name="csrf-token" content="{{ csrf_token() }}">

然后,您可以指示像 jQuery 这样的库自动将令牌添加到所有请求头中。这为使用传统 JavaScript 技术的 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 头中。

[!NOTE]
默认情况下,resources/js/bootstrap.js 文件包含 Axios HTTP 库,该库会自动为您发送 X-XSRF-TOKEN 头。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/laravel/12.x/cs...

译文地址:https://learnku.com/docs/laravel/12.x/cs...

上一篇 下一篇
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
贡献者:4
讨论数量: 1
发起讨论 只看当前版本


FakeSPrite
input 里面的 csrf 和 @csrf 的区别?
0 个点赞 | 5 个回复 | 问答 | 课程版本 5.8