需要通过CURL在PHP中共享到同一域上的LOCAL psuedo服务器的会话



我正在使用本地php文件构建一个应用程序,该文件接受post/get输入并返回JSON结果。我这样做是为了消除前端和后端操作的耦合,因为最终可以将后端移动到其他地方(这很好,因为你可以只使用浏览器和URL变量来测试后端操作。

需要明确的是,我没有立即甚至长期的计划来实际分离它们:现在它们在同一个文件夹中的同一台服务器上——我只有一个backend.php文件,假装是远程服务器,这样我就可以练习解耦了。这个问题的胜利意味着调用CURL并让后端接收会话,后端可以更改/更新/添加到会话,前端可以看到所有更改(基本上是前后一个会话(。

问题是,我一直在努力让两人之间的对话发挥作用。当我用Javascript发出AJAX请求时,会话工作得很好,因为它是在同一台服务器上加载的页面,所以session_start((就可以工作了。但是当我CURL时,会话数据不会被传输。

我已经和这个问题斗争了几个月了,所以我的卷曲函数非常混乱,但我不知道是什么神奇的组合让它发挥作用。没有多少SO问题或在线指南,我一直能够在这种情况下找到工作:

// Call the backend using the provided URL and series of name/value vars (in an array)
function backhand($data,$method='POST') {
$url = BACKEND_URL;
// Make sure the backend knows which session in the db to connect to
//$data['session_id'] = session_id();
// Backend will send this back in session so we can see the the connection still works.
//$data['session_test'] = rand();

$ch = curl_init();
if ('POST' == $method) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$get_url = sprintf("%s?%s", $url, http_build_query($data));
$_SESSION['diag']['backend-stuff'][] = $get_url;
if ('GET' == $method) {
curl_setopt($ch, CURLOPT_PUT, 1);
$url = $get_url;
}

// Optional Authentication:
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
#       curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
#       curl_setopt($ch, CURLOPT_VERBOSE, 1);
#       curl_setopt($ch, CURLOPT_USERAGENT,$_SERVER['HTTP_USER_AGENT']);
// Retrieving session ID 
// $strCookie = 'PHPSESSID=' . $_COOKIE['PHPSESSID'] . '; path=/';    
$cookieFile = "cookies.txt";
if(!file_exists($cookieFile)) {
$fh = fopen($cookieFile, "w");
fwrite($fh, $_SESSION);
fclose($fh);
}
#curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
#curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
#curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); // Cookie aware
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile); // Cookie aware
// We pass the sessionid of the browser within the curl request
curl_setopt( $ch, CURLOPT_COOKIEFILE, $strCookie ); 
#       session_write_close();
// Have to pause the session or the backend wipes the front
if (!$result = curl_exec($ch)) {
pre_r(curl_getinfo($ch));
echo 'Cerr: '.curl_error($ch);
}
curl_close($ch);
#       session_start();
// "true" makes it return an array
return json_decode($result,true);
}

我从前端调用这样的函数,从后端获取结果:

// Get user by email or ID
function get_user($emailorid) {
// If it's not an email, see if they've been cached. If so, return them
if (is_numeric($emailorid) && $_SESSION['users'][$emailorid])
return $_SESSION['users'][$emailorid];
return backhand(['get_user'=>$emailorid]);
}

所以如果我叫";get_user"在前面的任何地方,它都会跳到后面,运行数据库查询,并将其全部转储到JSON中,JSON在值的关联数组中返回给我。这很好,但会话数据无法正常保存,这会导致问题。

我甚至尝试了一段时间的DB会话,但这也不一致。我没有什么想法了,可能不得不通过使用数据库和自定义功能来构建某种替代会话功能,但我希望这种CAN能工作。。。我只是还没想好怎么做。

如果后端web服务器位于不同的服务器上,则可以保留文件系统存储并共享存储NFS会话的文件目录。

您也可以使用http://www.php.net/manual/en/function.session-set-save-handler.php为会话设置不同的存储处理程序,但我不确定将它们存储在数据库中是否适合I/O。

经过暴力尝试和错误后,这似乎奏效了:

function backhand($data,$method='POST') {
$url = BACKEND_URL;
// Make sure the backend knows which session in the db to connect to
//$data['session_id'] = session_id();
// Backend will send this back in session so we can see the the connection still works.
$data['session_test'] = rand();
$ch = curl_init();
if ('POST' == $method) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$get_url = sprintf("%s?%s", $url, http_build_query($data));
$_SESSION['diag']['backend-stuff'][] = $get_url;
if ('GET' == $method) {
curl_setopt($ch, CURLOPT_HTTPGET, 1);
$url = $get_url;
}
// Optional Authentication:
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
// required or it writes the data directly into document instead of putting it in a var below
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);         
#curl_setopt($ch, CURLOPT_USERAGENT,$_SERVER['HTTP_USER_AGENT']); 
// Retrieving session ID 
$strCookie = 'PHPSESSID=' . $_COOKIE['PHPSESSID'] . '; path=/';    
// We pass the sessionid of the browser within the curl request
curl_setopt( $ch, CURLOPT_COOKIE, $strCookie );  
curl_setopt($ch, CURLOPT_COOKIEJAR, 'somefile'); 
curl_setopt($ch, CURLOPT_COOKIEFILE, APP_ROOT.'/cookie.txt'); 
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 5000); 
// Have to pause the session or the backend wipes the front
session_write_close();
if (!$result = curl_exec($ch)) {
pre_r(curl_getinfo($ch));
echo 'Cerr: '.curl_error($ch);
}
@session_start();
curl_close($ch);
// "true" makes it return an array
return json_decode($result,true);
}

最新更新