基于CURL和PHP会话的身份验证

基于CURL和PHP会话的身份验证,php,cakephp-3.0,Php,Cakephp 3.0,我在https://app.example.com。应用程序要求用户登录;如果他们没有登录,他们将被重定向到https://app.example.com/login.php尝试访问此域上的任何URL时 用户成功登录后,应用程序将使用本机PHP会话来维护登录状态 我们在https://db.example.com。这是用CakePHP3构建的。它被配置为用户将无法访问此域上的任何URL,除非他们通过https://app.example.com首先。这是通过将会话.cookie\u域配置为.ex

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

用户成功登录后,应用程序将使用本机PHP会话来维护登录状态

我们在
https://db.example.com
。这是用CakePHP3构建的。它被配置为用户将无法访问此域上的任何URL,除非他们通过
https://app.example.com
首先。这是通过将
会话.cookie\u域
配置为
.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'
    ]
];
有一个脚本包含在
db.example.com
上的
app.example.com
中,它在每个请求上运行。这与读取会话cookie的能力相结合,意味着我们在用户访问
db.example.com
上的任何内容之前检查用户是否已登录;如果没有,它们将被重定向到
app.example.com/login.php

到目前为止,一切正常

问题是,我试图在
db.example.com
上的部分应用程序中向
db.example.com
上的另一个URL发出一个CURL请求(使用Cake的内置功能:),但响应是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'
    ], 

}
我已经读过了,但是看不到还有什么可以配置来解决这个问题

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

环境详情:

  • app.example.com
    db.example.com
    都在同一台服务器上
  • 两者都使用PHP7.0.33
  • db.example.com
    使用CakePHP 3.5.13作为框架;但是
    app.example.com
    使用普通的PHP(没有框架)
  • Web服务器是Apache2/CentOS

HTTP客户端不会自动填充来自其运行的应用程序的Cookie或任何其他应用程序状态,正如@misorude在评论中提到的,您的代码不会向客户端设置任何Cookie,因此不会发送任何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的正确方法之前,不会填充它,即
getCookie()
getCookie()
getCookieData()
,或
getCookieCollection()

另见


我看不到您在代码中任何地方处理发出cURL请求的会话cookie。收到任何响应的cookie都将存储在“Http\Client的原始实例”(quote docs)中,但因为您是从
$Http=new Client()开始的在这里,我认为在这一点上不应该包含任何cookies。@misorude这是一个有趣的问题,尽管我不知道如何更改/修复它。我的理解是,因为我已经在两个子域之间配置了“共享会话”和
PHPSESSID
,所以它应该可以工作。在浏览器中一切正常,但我承认这里会有所不同,因为是服务器(而不是浏览器)发出请求?您链接到的问题已经解释了使用本机cURL需要做什么-需要设置CURLOPT_COOKIEJAR/CURLOPT_COOKIEFILE。检查如何使用guzzle完成此操作。(不确定这是CakePHP使用的,还是它有自己的HTTP客户端实现?
调用未定义的方法App\Controller\FooController::getRequest()。如果我用
$this->request->cookies['PHPSESSID']
填充
$config['cookies']['PHPSESSID']
(或硬编码字符串),它仍然给出了302和相同的问题。@Andy
getRequest()
仅在CakePHP 3.6中可用,我已经更新了示例。对于您的问题,我没有任何进一步的建议,因为所示的示例按原样工作,您必须进行一些调试,以检查出了什么问题,使用网络嗅探器检查请求是否正确发出,和/或检查访问您的普通PHP应用程序的请求的确切外观,确保请求的会话有效,没有任何其他要求(如referer/ip/etc检查)…我将此标记为正确答案,因为@ndm所写的内容是正确的。我发现我遇到的错误是由于我们的普通PHP应用程序(
app.example.com
)上的脚本造成的,而不是会话cookie的传递方式。但是,仍然需要此答案中的信息。