PHP会话变量在模拟Cordova应用程序时不可用


PHP session variables not available when emulating Cordova App

我受不了了。

我正在使用apache cordova构建一个移动应用程序,其中jQuery AJAX和PHP被用来与服务器和数据库进行通信。我第一次发现这个问题是当我遇到队友没有的错误时,我们使用相同的代码。在我们的一些PHP代码中,我们使用$_SESSION变量来存储数据,但在我的机器上运行应用程序时,它没有被正确存储。下面是一个不工作的代码示例:

<?php
header('Access-Control-Allow-Origin : *');
include 'connection.php';
$userId = $_SESSION["userId"];
$query = "SELECT * ".
         "FROM `db`.`users` ".
         "WHERE `userId` = $userId;";
$result = $conn->query($query);
$result_array = array();
while($row = mysqli_fetch_assoc($result))
{
    $result_array[] = $row;
}
echo json_encode($result_array);

在此之前运行的页面中,调用包含以下行的不同php文件:

$_SESSION["userId"] = $userId;

include connection.php包含所有我们的用户/登录信息以及session_start();之前的任何东西。解决方案是这样的:当我构建应用程序并在设备上测试它时,此错误不会发生。只有在我的机器上通过chrome浏览器窗口中的ripple模拟器调试应用程序时才会发生这种情况。因为我不想如此频繁地创建新构建,所以我更改了代码,使用sessionStorage将数据存储在前端,并且不得不禁用模拟器上的跨域代理设置。

这就是我认为错误的地方:除非我将跨域代理设置为"禁用",否则我的AJAX调用都不会成功,但如果我这样做,PHP $_SESSION不再工作(我发现会话id只是重置每个新调用)。我的队友可以调试模拟器很好,他的跨域代理设置为"本地"。当我以这种方式尝试时,所有AJAX调用都会再次出错。

还有-最后一件事要注意:当我在web浏览器中运行应用程序时,不使用ripple模拟器或任何东西,一切都运行得很好。这将把问题缩小到纹波模拟器的具体问题上。

对于CORS和AJAX请求,我是一个新手,但是在发表之前我做了一些认真的研究,这是我最后的选择。我会经常监控这个问题,以防你需要我做任何其他事情来帮助我解决这个问题。谢谢!

EDIT:下面是我从命令行运行ripple emulate时得到的错误,在进行了一些建议的更改之后,这是我之前得到的相同的错误:

 C:'Users'Brian'Documents'HoH Docs'Source Code'gitDev'HoH'www>ripple emulate
INFO: Server instance running on: http://localhost:4400
INFO: CORS XHR proxy service on: http://localhost:4400/ripple/xhr_proxy
INFO: JSONP XHR proxy service on: http://localhost:4400/ripple/jsonp_xhr_proxy
INFO: Could not find cordova as a local module. Expecting to find it installed g
lobally.
INFO: Using Browser User Agent (String)
INFO: Proxying cross origin XMLHttpRequest - http://www.server.com/php/
signIn.php?email=b_dz@gmail.com&password=test
_http_outgoing.js:347
      throw new TypeError(
      ^
TypeError: Trailer name must be a valid HTTP Token ["access-control-allow-origin
 "]
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:347:13)
    at ServerResponse.res.setHeader (C:'Users'Brian'AppData'Roaming'npm'node_mod
ules'ripple-emulator'node_modules'express'node_modules'connect'lib'patch.js:59:2
2)
    at Request.pipeDest (C:'Users'Brian'AppData'Roaming'npm'node_modules'ripple-
emulator'node_modules'request'main.js:723:12)
    at C:'Users'Brian'AppData'Roaming'npm'node_modules'ripple-emulator'node_modu
les'request'main.js:614:14
    at Array.forEach (native)
    at ClientRequest.<anonymous> (C:'Users'Brian'AppData'Roaming'npm'node_module
s'ripple-emulator'node_modules'request'main.js:613:18)
    at ClientRequest.g (events.js:260:16)
    at emitOne (events.js:77:13)
    at ClientRequest.emit (events.js:169:7)
    at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:433:21
)

并在请求时从Fiddler Web调试器中获取这个:

The connection to 'localhost' failed. <br />Error: ConnectionRefused (0x274d). <br />System.Net.Sockets.SocketException No connection could be made because the target machine actively refused it 127.0.0.1:4400                                                                                                                                                                                                                                                                                                     

这很可能是你的问题:

header('Access-Control-Allow-Origin : *');
include 'connection.php';

在包含启动会话的连接文件之前,向浏览器发送头文件。

在某些测试环境中,可能会打开输出缓冲,因此可以正常工作。但是,在您的环境中,似乎不是这样,因此connection.php中的session_start()将失败。

你不应该在调用session_start()之前向浏览器输出任何内容,所以在这种情况下,你应该将header()调用移到include下面:

include 'connection.php';
header('Access-Control-Allow-Origin : *');

您可能可以在服务器错误日志中验证这是问题。

您可能必须在ajax请求中设置header

如果你正在使用jQuery ajax方法,然后添加下面的选项

xhrFields: {
    withCredentials: true
}

或者使用XMLHttpRequest对象发送ajax请求那么它应该在

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);

来自不同域的XmlHttpRequest响应不能设置cookie值,除非withCredentials设置为true在发出请求之前,不考虑访问控制头值。