首页 > 解决方案 > 执行 CURL Post 请求时 CakePHP 中的 CSRF 令牌

问题描述

我对 CakePHP 很陌生,我一直在尝试解决这个问题一段时间。

正在发生的事情如下:

我基本上是在尝试使用 php POST CURL 从不同的 IP/域到 Cake 应用程序获得结果。但是,每次我这样做时,我都会在 CakePHP 应用程序日志“Missing CSRF Token Cookie”中不断收到错误消息。

我已经浏览了在线文档和各种帖子,但我仍然不完全理解这一点。

我希望这里有人可以更好地解释这个错误的含义。与 php 建立 CURL 连接时如何传递 CSRF 令牌?更重要的是如何获得 Cake 应用程序 CSRF Token?

对不起,如果这听起来像一个愚蠢的问题,但我真的迷路了,不知道还能去哪里找。我提前感谢您的帮助。

编辑 1 我们正在尝试将数据添加到系统中,当我们执行 GET 请求时没有问题,该请求运行良好。问题来自执行 POST 请求。

编辑 2 我正在添加我的 AppController 代码和执行所有功能的其他控制器。我想要做的是让 POST 工作,所以我可以实现添加或编辑存储在数据库中的数据的功能。

应用控制器.php

namespace App\Controller;

use Cake\Controller\Controller;
use Cake\Event\Event;

class AppController extends Controller
{
    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('RequestHandler', [
            'enableBeforeRedirect' => false,
        ]);
        $this->loadComponent('Flash');
    }
}

WebservicesController.php

namespace App\Controller;
use Cake\Event\Event;

class WebservicesController extends AppController{
  protected   $responseBody   =   [];

  public function beforeRender(Event $event){
    foreach($this->responseBody as $responseKey=>$response){

       $this->set($responseKey, $response);
    }
    $this->set('_serialize', array_keys($this->responseBody));

  }

  public function initialize(){
    parent::initialize();
    $this->RequestHandler->renderAs($this, 'json');
  }

  public function index(){
    ///getting data 
    $this->request->allowMethod(['get']);
    $id = $this->request->getQuery("id");
    $this->responseBody["statusCode"] = 200;
    $this->responseBody['statusDescription'] = "";
    $this->responseBody['data'] = array();
  }

  public function getOneItem(){
    $this->request->allowMethod(['post']);

    if ($this->request->is('post')) {
      //Add/Edit Data in here.
      $id = $this->request->getQuery("id");
      $this->responseBody["statusCode"] = 200;
      $this->responseBody['statusDescription'] = "";
      $this->responseBody['data'] = array();
    }
  }
}

标签: phpcurlpostcakephpcsrf

解决方案


CSRF 是一种通过生成令牌和一些隐藏字段来防止 HTML 表单篡改的机制。使用 curl,您没有 HTML 表单,因此不会生成令牌,因此这种控制是不可能的。您必须禁用该安全性。

一个简单的答案可能是:在 appController.php 中禁用 CSRF 安全性。

if (!$this->request->is('ajax')) {
    $this->loadComponent('Security');
    $this->loadComponent('Csrf');
}

当然,您可以无条件地执行此操作,并在每个其他控制器中的 initialize() 函数中重新启用它。但你不会想要那样做。

一种更好的解决方案是在特定控制器中禁用 Security AND CSRF 以执行特定操作,如文档中所述,在两个不同的位置:

  1. https://book.cakephp.org/3.0/en/controllers/components/csrf.html#disabling-the-csrf-component-for-specific-actions
  2. https://book.cakephp.org/3.0/en/controllers/components/security.html#disabling-security-component-for-specific-actions

在我的情况(和你的情况)中,我想通过 POST 和 curl 添加一些东西。

所以控制器中的这些行有效:

public function beforeFilter(Event $event)
{
    $this->Security->setConfig('unlockedActions', ['add']);
    $this->getEventManager()->off($this->Csrf);
}

卷曲命令(在这里我发布一个文件和一些 id,但这可能是任何东西):

 curl -k -X POST --cookie CAKEPHP=xxxx -F "file=@index.jpeg" -F fk_id=1 https://hostname/cake/files.json

结果是对象的 json 表示。

{
    "file": {
        "fk_id": 1,
        "file": {
            "tmp_name": "\/tmp\/phpBUaHon",
            "error": 0,
            "name": "index.jpeg",
            "type": "image\/jpeg",
            "size": 7861
        },
        "created": "2018-08-22T06:08:06+00:00",
        "modified": "2018-08-22T06:08:06+00:00",
        "id": 14
    }
}

推荐阅读