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, PATCHDELETE 为秘密会话值恶意的应用程序无法访问请求。

阻止 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 标头。

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

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
上一篇 下一篇
Summer
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
贡献者:7
讨论数量: 0
发起讨论 只看当前版本


暂无话题~