Cakephp 3.5.6禁用控制器的CSRF中间件

问题描述 投票:3回答:2

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

使用以下命令可以在特定请求中禁用3.5.0之前的CSRF组件:

$this->eventManager()->off($this->Csrf);
cakephp cakephp-3.0 csrf middleware
2个回答
10
投票

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

将中间件应用于特定的路由范围(甚至路由)

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

// config/routes.php

use Cake\Http\Middleware\CsrfProtectionMiddleware;

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范围内连接的路由。

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

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

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

有条件地手动应用中间件

另一种方法是在适用时手动应用中间件。为了能够做到这一点,您必须创建一个自定义中间件处理程序,以便您可以访问当前请求对象,从中可以提取controller参数,然后您必须在处理程序内调用CSRF中间件,有点像这样:

// src/Application.php

// ...
use Cake\Http\Middleware\CsrfProtectionMiddleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

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;
    }
}

请注意,您必须在路由中间件之后应用自定义中间件,因为这是设置控制器信息的位置。

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

if (mb_strpos($request->getUri()->getPath(), '/api/') === false) {
    $csrf = new CsrfProtectionMiddleware([
        'httpOnly' => true
    ]);

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

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

也可以看看


1
投票

我认为在Cake 3.6中,你应该从中间件中删除CsrfProtectionMiddleware:

queue:src / Application.php

     public function middleware($middlewareQueue)
      {
           $middlewareQueue
        // Catch any exceptions in the lower layers,
        // and make an error page/response
        ->add(ErrorHandlerMiddleware::class)

        // Handle plugin/theme assets like CakePHP normally does.
        ->add(new AssetMiddleware([
            'cacheTime' => Configure::read('Asset.cacheTime')
        ]))

        // Add routing middleware.
        // Routes collection cache enabled by default, to disable route caching
        // pass null as cacheConfig, example: `new RoutingMiddleware($this)`
        // you might want to disable this cache in case your routing is extremely simple
        ->add(new RoutingMiddleware($this, '_cake_routes_'));


        // Add csrf middleware.
        //            ->add(new CsrfProtectionMiddleware([
        //                'httpOnly' => true
        //            ]));

        return $middlewareQueue;
     }
© www.soinside.com 2019 - 2024. All rights reserved.