官方文档中文版翻译工作仍在进行中,欢迎 参与翻译。
CSRF 防护
默认的 Web 应用模板包含 CSRF 防护中间件。但在非默认 Web 应用中可能需要先安装它:
$ composer require spiral/csrf
然后把它的引导程序添加到 App.php 中来启用:
[
//...
Spiral\Bootloader\Http\CsrfBootloader::class,
]
CSRF 扩展会启用 Spiral\Csrf\Middleware\CsrfMiddleware
中间件,以确保每个用户有唯一的 token.
启用防火墙
CSRF 扩展提供了两个中间件,这两个中间件为引用提供全局或路由级别的防护。如果要对除了 GET
, HEAD
, OPTIONS
以外的所有请求提供防护,需要使用 Spiral\Csrf\Middleware\CsrfFirewall
:
use Spiral\Csrf\Middleware\CsrfFirewall;
// ...
public function boot(RouterInterface $router)
{
$route = new Route('/', new Target\Action(HomeController::class, 'index'));
$router->setRoute(
'index',
$route->withMiddleware(CsrfFirewall::class)
);
}
提示,如果要对所有的 HTTP 动词提供防护,需要使用
Spiral\Csrf\Middleware\StrictCsrfFirewall
.
使用
一旦启用防护,每个请求都必须通过 PSR-7 属性 csrfToken
来提供合法的 token.
在控制器或者视图中,可以读取请求中的 token:
public function index(ServerRequestInterface $request)
{
$csrfToken = $request->getAttribute('csrfToken');
}
用户发出的每个 POST
, PUT
或者 DELETE
请求必须在 POST 参数 csrf-token
或者 X-CSRF-Token
头信息中携带合法的 token.
public function index(ServerRequestInterface $request)
{
$form = '
<form method="post">
<input type="hidden" name="csrf-token" value="{csrfToken}"/>
<input type="text" name="value"/>
<input type="submit"/>
</form>
';
$form = str_replace(
'{csrfToken}',
$request->getAttribute('csrfToken'),
$form
);
return $form;
}
全局启用
如果需要全局启用 CSRF 防护,可以通过 HttpBootloader
引导程序注册 Spiral\Csrf\Middleware\CsrfFirewall
或者 Spiral\Csrf\Middleware\StrictCsrfFirewall
:
use Spiral\Csrf\Middleware\CsrfFirewall;
// ...
public function boot(HttpBootloader $http)
{
$http->addMiddleware(CsrfFirewall::class);
}