【问题标题】:CURL and PHP session based authentication基于 CURL 和 PHP 会话的身份验证
【发布时间】:2019-05-17 22:41:53
【问题描述】:

我在https://app.example.com 上有一个申请。该应用程序需要用户登录;如果他们登录,则在尝试访问此域上的任何 URL 时,他们将被重定向到 https://app.example.com/login.php

当用户成功登录后,应用程序使用原生 PHP 会话来维护登录状态。

我们在https://db.example.com 上有一个单独的应用程序。这是使用 CakePHP 3 构建的。它被配置为用户将无法访问此域上的任何 URL,除非他们首先通过 https://app.example.com 登录。这是通过将session.cookie_domain 配置为.example.com 然后将用于会话的cookie 设置为PHPSESSID 来完成的:

// config/app.php on db.example.com
'Session' => [
    'defaults' => 'php',
    'cookie' => 'PHPSESSID',
    'timeout' => '0',
    'ini' => [
        'session.cookie_domain' => '.example.com',
        'session.cookie_httponly' => 'off'
    ]
];

app.example.com 上的 db.example.com 包含一个脚本,该脚本在每个请求上运行。这 - 结合读取会话 cookie 的能力 - 意味着我们正在检查用户是否已登录,然后他们才能访问 db.example.com 上的任何内容;如果没有,他们会被重定向到app.example.com/login.php

到目前为止一切正常

问题是我正在尝试在db.example.com 上的应用程序的一部分中向db.example.com 上的另一个URL 发出CURL 请求(为此使用Cake 的内置功能:https://book.cakephp.org/3.0/en/core-libraries/httpclient.html),但为了响应是一个 302 重定向到https://app.example.com/login.php

请求是从https://db.example.com/foohttps://db.example.com/bar - 这也需要在POST 数据中的id 参数 - 像这样:

// Request made by /foo:
public function foo()
{
    $this->autoRender = false;

    $http = new Client();

    $response = $http->post('https://db.example.com/bar', [
        'id' => '12345'
    ]);

    debug($response);
}

上面的输出是一个 HTTP 302,其位置设置为app.example.com 上的登录页面:

object(Cake\Http\Client\Response) {
    [protected] code => (int) 302
    [protected] cookies => null
    [protected] reasonPhrase => 'Found'

// ...

'Set-Cookie' => [
    (int) 0 => 'PHPSESSID=g9aeqt2acol6av03rqul2puo20; path=/; domain=.example.com; secure'
    ],
'Location' => [
    (int) 0 => 'https://app.example.com/login.php'
    ], 

}

我已阅读Keeping session alive with Curl and PHP,但看不到还有什么配置可以解决这个问题?

Set-Cookie 具有正确的会话/cookie/域详细信息时,我也不理解调试信息的cookies => null 部分。

环境详情:

  • app.example.comdb.example.com 在同一台服务器上。
  • 两者都使用 PHP 7.0.33
  • db.example.com 使用 CakePHP 3.5.13 作为框架;但app.example.com 使用原生 PHP(无框架)。
  • Web 服务器是 Apache 2 / CentOS。

【问题讨论】:

  • 我没有看到您在发出 cURL 请求的代码中的任何地方处理会话 cookie。收到的任何响应的 Cookie 都将存储在 “在 Http\Client 的原始实例中”(引用文档) - 但由于您在这里以 $http = new Client(); 开头,我认为不应包含 任何 cookie。
  • @misorude 虽然我不明白如何更改/修复它,但这是一个有趣的观点。我的理解是,因为我已经在两个子域之间配置了“共享会话”和PHPSESSID,所以它应该可以工作。在浏览器中一切正常,但我接受它在这里会有所不同,因为它是服务器(而不是浏览器)发出请求?
  • 您链接到的问题已经解释了使用本机 cURL 需要做什么 - 需要设置 CURLOPT_COOKIEJAR/CURLOPT_COOKIEFILE。检查 stackoverflow.com/q/45406915/10283047 以了解如何使用 guzzle 完成此操作。 (不确定 CakePHP 是否使用它,或者它是否有自己的 HTTP 客户端实现?)

标签: php cakephp-3.0


【解决方案1】:

HTTP 客户端不会使用正在运行的应用程序中的 cookie 或任何其他应用程序状态自动填充自身,正如 @misorude 在 cmets 中所提到的,您的代码不会将任何 cookie 设置为客户端,因此它不会发送任何内容。

您必须自己设置所需的会话 cookie,例如对于单个请求:

$data = [
    'id' => '12345'
];
$config = [
    'cookies' => [
        //'PHPSESSID' => $this->request->getSession()->id() // before CakePHP 3.6
        'PHPSESSID' => $this->getRequest()->getSession()->id()
    ]
];
$response = $http->post('https://db.example.com/bar', $data, $config);

响应对象上假定的 cookies 属性为空是一个调试显示“问题”,该类没有自定义调试输出,因此使用 PHP 默认值,其中将包括受保护的属性,如 $cookies,但是,在您调用正确的方法来读取 cookie 之前,它不会被填充,即 getCookies()getCookie()getCookieData()getCookieCollection()

另见

【讨论】:

  • Call to undefined method App\Controller\FooController::getRequest()。如果我用$this->request->cookies['PHPSESSID'] 填充$config['cookies']['PHPSESSID'](或硬编码字符串),它仍然会给出302 和同样的问题。
  • @Andy getRequest() 仅适用于 CakePHP 3.6,我已经更新了示例。我对您的问题没有任何进一步的建议,因为所示示例按原样工作,您必须进行一些调试以检查问题所在,使用网络嗅探器检查请求是否正确发出,和/或检查您的原生 PHP 应用程序的请求到底是什么样的,确保请求的会话有效,没有任何其他要求(如引用/IP/等检查)...
  • 我将此标记为正确答案,因为@ndm 所写的是正确的。我发现我得到的错误是由于我们的普通 PHP 应用程序 (app.example.com) 上的脚本,而不是会话 cookie 的传递方式。但是,仍然需要此答案中的信息。
猜你喜欢
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2017-04-13
  • 2015-12-24
  • 2013-12-29
相关资源
最近更新 更多