Skip to content

CSRF 保护

介绍

Laravel 使得保护您的应用程序免受跨站请求伪造(CSRF)攻击变得简单。跨站请求伪造是一种恶意攻击类型,未经授权的命令会以经过身份验证的用户的名义执行。

Laravel 会为应用程序管理的每个活动用户会话自动生成一个 CSRF "令牌"。此令牌用于验证经过身份验证的用户是否确实在向应用程序发出请求。

每当您在应用程序中定义 HTML 表单时,您都应在表单中包含一个隐藏的 CSRF 令牌字段,以便 CSRF 保护中间件可以验证请求。您可以使用 @csrf Blade 指令生成令牌字段:

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

VerifyCsrfToken 中间件包含在 web 中间件组中,将自动验证请求输入中的令牌是否与会话中存储的令牌匹配。

CSRF 令牌与 JavaScript

在构建 JavaScript 驱动的应用程序时,让您的 JavaScript HTTP 库自动将 CSRF 令牌附加到每个传出的请求中是很方便的。默认情况下,resources/js/bootstrap.js 文件会将 csrf-token 元标记的值注册到 Axios HTTP 库中。如果您不使用此库,则需要为您的应用程序手动配置此行为。

从 CSRF 保护中排除 URI

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

通常,您应将这些类型的路由放在 RouteServiceProvider 应用于 routes/web.php 文件中所有路由的 web 中间件组之外。但是,您也可以通过将其 URI 添加到 VerifyCsrfToken 中间件的 $except 属性中来排除这些路由:

php
<?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/*',
    ];
}
lightbulb

运行测试时,CSRF 中间件会自动禁用。

X-CSRF-TOKEN

除了检查作为 POST 参数的 CSRF 令牌外,VerifyCsrfToken 中间件还会检查 X-CSRF-TOKEN 请求头。您可以,例如,将令牌存储在 HTML meta 标签中:

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

然后,一旦您创建了 meta 标签,您可以指示像 jQuery 这样的库自动将令牌添加到所有请求头中。这为您的基于 AJAX 的应用程序提供了简单、方便的 CSRF 保护:

php
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});
lightbulb

默认情况下,resources/js/bootstrap.js 文件会将 csrf-token 元标记的值注册到 Axios HTTP 库中。如果您不使用此库,则需要为您的应用程序手动配置此行为。

X-XSRF-TOKEN

Laravel 将当前的 CSRF 令牌存储在 XSRF-TOKEN cookie 中,该 cookie 会包含在框架生成的每个响应中。您可以使用 cookie 值设置 X-XSRF-TOKEN 请求头。

此 cookie 主要是作为一种便利发送的,因为一些 JavaScript 框架和库(如 Angular 和 Axios)会自动将其值放入 X-XSRF-TOKEN 头中。