跳转到主要内容

简介

CSRF(Cross-Site Request Forgery)是一种冒充已登录用户,让其发送非本人意图请求的攻击。 例如,你的应用有一个 POST /user/email 接口,用于修改邮箱地址。如果攻击者在另一个网站上放置了自动向该 URL 提交的表单,那么用户可能在毫无察觉的情况下被修改了邮箱。 在 Laravel 13 中,由于 web 中间件组已内置相关机制,CSRF 保护默认处于启用状态。

防御 CSRF 攻击

Laravel 的 PreventRequestForgery 中间件通过以下两个层面防御 CSRF:
  1. Origin 校验Sec-Fetch-Site 头)
  2. 令牌校验(会话级 CSRF 令牌)
它首先检查 Origin,若无法判定或校验失败,则回退到令牌校验。

Origin 校验

Laravel 首先检查 Sec-Fetch-Site,判断请求是否来自同一 Origin。这在 HTTPS 环境下尤其有效。 若 Origin 校验通过,则该请求会被直接放行。若未通过,则会像以往那样执行 CSRF 令牌校验。
Sec-Fetch-Site 的前提是通过 HTTPS 连接使用。在 HTTP 环境下 Origin 校验不会生效,令牌校验将成为主要的防御手段。

Origin-only 模式

你可以禁用令牌校验的回退,仅通过 Origin 校验来判断。
在 Origin-only 模式下,Origin 校验失败的请求将返回 403 而不是 419 如果你希望允许同站请求(例如跨子域请求),可以设置 allowSameSite

令牌校验

Laravel 会为每个会话生成 CSRF 令牌。可以通过 csrf_token() 或会话获取。
web 路由中创建 POSTPUTPATCHDELETE 表单时,务必包含 @csrf

排除 URI

对于像 Stripe Webhook 这样由外部服务发来的请求,有时需要将特定 URI 从 CSRF 保护中排除。
如果可能,请将 Webhook 路由放在 web 中间件组之外,并将排除设置控制在最小范围。

X-CSRF-TOKEN 头

Laravel 不仅会校验表单中的 _token,也会校验 X-CSRF-TOKEN 头。 首先,将令牌输出到 meta 标签。
然后将该值添加到 AJAX 请求头中。

X-XSRF-TOKEN 头

Laravel 还会发送加密过的 XSRF-TOKEN Cookie。Axios 或 Angular 在发送同源请求时,会自动将该值设置到 X-XSRF-TOKEN 头中。 因此,在 SPA 或 AJAX 实现中,某些情况下即使不手动编写请求头设置,CSRF 保护也能生效。

SPA 的注意事项

当在 SPA 中将 Laravel 作为 API 后端使用时,需要先获取 CSRF Cookie,再发送登录请求。
详细内容请参阅 Sanctum
最后修改于 2026年7月18日