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

查看:216
本文介绍了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 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范围内连接的路由.

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 Cake\Http\Middleware\CsrfProtectionMiddleware;
use Psr\Http\Message\ServerRequestInterface;

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 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 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天全站免登陆