【问题标题】:Failed CSRF check! in postman when trying POST method (API with slim 3)CSRF 检查失败!在邮递员中尝试 POST 方法(带有 slim 3 的 API)
【发布时间】:2018-05-05 21:05:53
【问题描述】:

我正在处理一个 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)

【问题讨论】:

    标签: rest csrf slim slim-3


    【解决方案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了解更多信息。

    【讨论】:

    • 谢谢,我决定采用你的第一种方法:仅对某些路由应用 CSRF。查看我的答案编辑以获取更多详细信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-19
    • 2021-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多