Cakephp 3.5.6 禁用控制器的 CSRF 中间件 [英] Cakephp 3.5.6 disable CSRF Middleware for controller

查看:34
本文介绍了Cakephp 3.5.6 禁用控制器的 CSRF 中间件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试禁用单个控制器 (API) 的 CSRF 检查,但我无法找到如何实现这一点.

I'm trying to disable the CSRF check for a single controller (API), but I'm unable to find how I'm able to achieve this.

3.5.0 之前的 CSRF 组件可以根据特定请求禁用:

The pre 3.5.0 CSRF Component had the ability to be disabled on certain request using:

$this->eventManager()->off($this->Csrf);

推荐答案

有两种方法可以做到这一点.

There are two ways to do that.

根据您创建的路由,您可以将中间件仅应用于特定范围,例如:

Depending on what routes you create, you can apply the middleware to specific scopes only, for example:

// config/routes.php

use CakeHttpMiddlewareCsrfProtectionMiddleware;

Router::scope('/', function ($routes) {
    $routes->registerMiddleware('csrf', new CsrfProtectionMiddleware([
        'httpOnly' => true
    ]));

    $routes->scope('/api', function ($routes) {
        // ...
    });

    $routes->scope('/blog', function ($routes) {
        $routes->applyMiddleware('csrf');
        // ...
    });

    $routes->scope('/cms', function ($routes) {
        $routes->applyMiddleware('csrf');
        // ...
    });
});

这只会将 CSRF 中间件应用于连接在 blogcms 范围内的路由.

This would apply the CSRF middleware only to the routes connected in the blog and cms scopes.

还可以将范围进一步缩小到路由级别,并将中间件应用于特定路由:

It's also possible to narrow things down further to route level, and apply the middleware on specific routes:

$routes
    ->connect('/blog/:action', ['controller' => 'Blogs'])
    ->setMiddleware(['csrf']);

这会将 CSRF 中间件仅应用于 /blog/* 路由.

This would apply the CSRF middleware to only the /blog/* routes.

另一种方法是在适用时手动应用中间件.从 CakePHP 3.8 开始,中间件有一个名为 whitelistCallback 的白名单方法,您可以在其中检查请求对象并返回一个布尔值来定义是否应用检查:

Another way would be to manually the apply the middleware when applicable. As of CakePHP 3.8, the middleware has a whitelisting method named whitelistCallback, inside of it you can check the request object and return a boolean that defines whether the checks are applied:

// src/Application.php

// ...
use CakeHttpMiddlewareCsrfProtectionMiddleware;
use PsrHttpMessageServerRequestInterface;

class Application extends BaseApplication
{
    // ...

    public function middleware($middleware)
    {
        $csrf = new CsrfProtectionMiddleware([
            'httpOnly' => true
        ]);
        $csrf->whitelistCallback(function (ServerRequestInterface $request) {
            $params = $request->getAttribute('params');
            return $params['controller'] !== 'Api';
        });

        $middleware
            // ...
            ->add(new RoutingMiddleware())

            ->add($csrf);

        return $middleware;
    }
}

在早期的 CakePHP 版本中,您必须创建一个自定义中间件处理程序,以便您可以访问当前的请求对象,您可以从中提取 controller 参数,然后您必须调用处理程序中的CSRF中间件,大致如下:

In earlier CakePHP versions you'll have to create a custom middleware handler so that you can access the current request object, from which you can extract the controller parameter, and then you have to invoke the CSRF middleware inside your handler, something along the lines of this:

// src/Application.php

// ...
use CakeHttpMiddlewareCsrfProtectionMiddleware;
use PsrHttpMessageResponseInterface;
use PsrHttpMessageServerRequestInterface;

class Application extends BaseApplication
{
    // ...

    public function middleware($middleware)
    {
        $middleware
            // ...
            ->add(new RoutingMiddleware())

            ->add(function (
                ServerRequestInterface $request,
                ResponseInterface $response,
                callable $next
            ) {
                $params = $request->getAttribute('params');
                if ($params['controller'] !== 'Api') {
                    $csrf = new CsrfProtectionMiddleware([
                        'httpOnly' => true
                    ]);

                    // This will invoke the CSRF middleware's `__invoke()` handler,
                    // just like it would when being registered via `add()`.
                    return $csrf($request, $response, $next);
                }

                return $next($request, $response);
            });

        return $middleware;
    }
}

请注意,在这两种情况下,您都必须将中间件放在路由中间件之后,因为这是设置控制器信息的地方.

Note that in both cases you must put the middleware after the routing middleware, as that is where the controller information is being set.

如果适用,您还可以针对请求 URL 而不是路由参数进行测试,例如:

If applicable, you could also test against the request URL instead of the routing paramteres, for example something like this:

if (mb_strpos($request->getUri()->getPath(), '/api/') === false) {
    // apply CSRF checks
}

这样做时,中间件不会被限制在路由中间件之后,理论上你可以把它放在你想要的任何位置.

When doing so, the middleware wouldn't be restricted to be placed after the routing middleware, you could theoretically place it at whichever position you want.

这篇关于Cakephp 3.5.6 禁用控制器的 CSRF 中间件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆