CSRF检查失败!在邮递员尝试POST方法时(带有超薄3的API)

时间:2018-05-05 21:05:53

标签: rest csrf slim slim-3

我正在使用Slim 3项目,我安装了CSRF package(" slim / csrf":" ^ 0.8.2",)

为了发出POST请求我正在使用邮递员。发送操作时,我收到以下错误:

  

CSRF检查失败!

以下是我的API路线(在这种情况下,重点关注POST路线):

<?php

/* RESTful endpoints or routes */

use App\Controllers\api\users\UserController;

    $app->group('/api',function () use ($app){
        $app->group('/users', function () {
            $this->get('', UserController::class.':index');
            $this->get('/{id}', UserController::class.':show');
            $this->post('', UserController::class.':store');
        });
    });

这是控制器应该从POST请求中获取信息,我收到错误:

//Save a user via API
    public function store($request,$response,$args)
    {
        //todo: validation!
        var_dump($request->getParams());//todo: CSRF check failed!
        die();
    }

这是我注册CSRF组件的地方:

//Register the CSRF Component
$container['csrf'] = function ($container){
    return new \Slim\Csrf\Guard();
};

我尝试了这个解决方案:https://stackoverflow.com/a/48266488/1883256但它没有用。

是否有任何解决方法可以使其正常工作?如何阻止CSRF在API路由上运行?

*已解决*

正如Zamrony P. Juhara建议的那样,我决定将CSRF应用于除了API路由之外的Web路由。

将我的所有网络路线分组:

    $app->group('',function ()use($app,$container){
        /* ******* H O M E ********** */
        require __DIR__ . '/web/home/home.php';
        /* ********** T O P I C  s ********** */
        require __DIR__ . '/web/topics/topics.php';

        /* ********** C O N T A C T *********** */
        require __DIR__ . '/web/contact/contact.php';

/* And so on and etcetera ....*/
        /* ********************************************************************************* */
    })->add($container->get('csrf'));//Adding CSRF protection only for web routes

例如,在topics.php路径文件中我有:

$app->group('/topics',function(){
    $this->get('',TopicController::class.':index');
    $this->get('/{id}',TopicController::class.':show')->setName('topics.show');
});

至于API路线,它们保持不变。

最后,在我的容器内,我评论了以下内容:

//$app->add($container->get('csrf')); //I've commented this line in order to add CSRF for specific routes (all except APIs ones)

1 个答案:

答案 0 :(得分:1)

您需要确保向路由或应用程序添加Slim\Csrf\Guard中间件(如果要为所有路由应用csrf)。例如

将csrf中间件应用于所有路由

$csrf = $container->csrf;
$app->add($csrf);

或仅申请某些路线

$csrf = $container->csrf;
$app->group('/api',function () use ($app, $csrf){
    $app->group('/users', function () {
        $this->get('', UserController::class.':index')
             ->add($csrf);
        $this->get('/{id}', UserController::class.':show');
        $this->post('', UserController::class.':store')
             ->add($csrf);
    });
});

您还需要确保有请求传递的Csrf令牌名称/值数据。当您使用Postman时,您需要找到一种方法来在执行POST之前获取令牌名称键/值对。

以下代码摘自Slim Csrf Readme

// CSRF token name and value
$nameKey = $this->csrf->getTokenNameKey();
$valueKey = $this->csrf->getTokenValueKey();
$name = $request->getAttribute($nameKey);
$value = $request->getAttribute($valueKey);

// Render HTML form which POSTs to /bar with two hidden input fields for the
// name and value:
// <input type="hidden" name="<?= $nameKey ?>" value="<?= $name ?>">
// <input type="hidden" name="<?= $valueKey ?>" value="<?= $value ?>">

阅读Slim Csrf Readme了解详情。