Cakephp 3.5.6 disable CSRF Middleware for controller

蓝咒 提交于 2019-11-28 12:50:20

There are two ways to do that.

Apply the middleware to specific routing scopes (or even routes)

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

// 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');
        // ...
    });
});

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']);

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

Conditionally apply the middleware manually

Another way would be to manually the apply the middleware when applicable. In order to be able to do that, 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 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;
    }
}

Note that you must apply your custom middleware after the routing middleware, as that is where the controller information is being set.

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) {
    $csrf = new CsrfProtectionMiddleware([
        'httpOnly' => true
    ]);

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

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

See also

sachin mishra

I think in Cake 3.6, you should remove CsrfProtectionMiddleware from middleware:

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;
     }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!