【发布时间】: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/foo 到https://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.com和db.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