jQuery POST 请求后 PHP 会话数据丢失

Posted

技术标签:

【中文标题】jQuery POST 请求后 PHP 会话数据丢失【英文标题】:PHP Session data lost after jQuery POST request 【发布时间】:2015-08-20 23:11:44 【问题描述】:

我知道这个问题似乎和它被问过很多次一样,但请继续阅读。

问题是,正如标题所暗示的,当我向另一个页面发出 POST 请求时,会话数据没有保存在我的 php 脚本中。

是的,所有脚本的第一行都有session_start();。 是的,我检查了 session_id 是否相同,确实如此。 apache 日志没有显示任何错误(我有它显示所有 错误) 我测试了会话是否可以创建用于创建/读取会话变量的简单页面,并且可以正常工作。当我使用 POST 请求时,它的行为很奇怪。

两个脚本都在同一个服务器上。

我将展示我编辑的代码,只是为了展示它的作用。

脚本 A

<?
session_start();

echo session_id()."<br>";
print_r($_SESSION);

require_once __DIR__ . '/include/config.php';

ini_set('session.use_cookies', 1);
ini_set('session.use_only_cookies', 1);

session_set_cookie_params(
    0,
    ini_get('session.cookie_path'),
    ini_get('session.cookie_domain'),
    isset($_SERVER['HTTPS']),
    true
);

$_SESSION['haygsdb18'] = true;
$_SESSION['user_name'] = '';
$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
$_SESSION['REMOTE_ADDR'] = md5($_SERVER['REMOTE_ADDR']);

$include_path =  str_replace($_SERVER['DOCUMENT_ROOT'],'',__DIR__);

?>

$.post(
    "<?=$include_path?>/include/ScriptB.php",
    OTP: OTP,
    function(data) 
        alert(data);
    
);

脚本 B

<?
session_start();

$msg = session_id()."\n";
$msg .= print_r($_SESSION,true);
exit($msg);
?>

这样我正在调试。脚本 B 显示相同的会话 id,但没有会话变量。

我想弄清楚它已经失去了理智。让我感到害怕的另一件事是服务器中另一个文件夹中的相同脚本(完全相同,复制粘贴)运行良好。

请帮忙...我的想法已经用完了。

更新:更多调试信息

我查看了由 php 在终端中使用 tail -f 创建的 sess 文件。加载脚本 A 时,变量被写入文件中,并且当进行 AJAX 调用时,文件被清空(不删除,只是清空)。

当脚本A执行$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);时,sess文件被写入HTTP_USER_AGENT|s:32:"2589a220583546006658f54ada687b45";,但是当脚本B执行$_SESSION['TEST'] = '1';时,sess文件中的所有内容被替换为C1Hw6hhbpX-jWhvbRfz_reKX4tT66bcNpYGLGzxEg7I.

大量调试.. 发现了一个奇怪的东西

我比较了 session_handler 如何在我使用相同登录脚本的其他系统中编写 sess 文件。在其他系统中,脚本 A 和脚本 B 将加密信息写入文件。问题是在这个特定系统中,脚本 A 没有使用任何加密写入文件,但脚本 B 是。

我怀疑脚本 B 期望会话信息被加密,所以因为它不是它无法读取变量并且它们已经消失了。当试图保持从脚本 B 到脚本 A 的变量时,也会发生同样的情况。

所以现在我的问题是,脚本 A 和脚本 B 怎么可能在我没有告诉他们这样做的情况下使用不同的 session_write 处理程序?我如何强迫他们使用相同的?

【问题讨论】:

我们需要脚本checkOTP.php的代码来检查.. 这是脚本 B.. 我将编辑问题 尝试,而不是使用退出,这可能会导致您的会话过早关闭,只是为了回显您正在调试的任何内容。我在调试东西时被逼疯了太多次,代码中某处的die() 语句干扰了会话的持续。 它没有改变结果。 【参考方案1】:

您的会话未写入磁盘或您正在使用的任何存储,因为在您进行 ajax 调用时脚本执行可能未完成。

您可以使用 session_write_close() 函数将会话数据保存到存储中(很可能是您的 /tmp/ 文件夹) http://php.net/manual/tr/function.session-write-close.php

<?php
session_start();
echo session_id()."<br>";
print_r($_SESSION);


ini_set('session.use_cookies', 1);
ini_set('session.use_only_cookies', 1);

session_set_cookie_params(0,ini_get('session.cookie_path'),ini_get('session.cookie_domain'),isset($_SERVER['HTTPS']),true);

$_SESSION['haygsdb18'] = true;
$_SESSION['user_name'] = '';
$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
$_SESSION['REMOTE_ADDR'] = md5($_SERVER['REMOTE_ADDR']);
//write the session before the script execution ends
session_write_close();

$include_path =  str_replace($_SERVER['DOCUMENT_ROOT'],'',__DIR__);
?>
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
    <script type="text/javascript">
            $(document).ready(function() 

                $.post("scriptB.php", OTP: "OTP", function(data) 
                    alert(data););

            );

    </script>

</head>
<body>

</body>
</html>

这是我的输出;

tdiiqame0i4ldshc8m20n8d9o6
Array
(
    [haygsdb18] => 1
    [user_name] => 
    [HTTP_USER_AGENT] => bc9d9d38aa0626db612842a1e0d09ea9
    [REMOTE_ADDR] => f528764d624db129b32c21fbca0cb8d6
)

【讨论】:

我想我尝试过这样做。我明天再试一次,告诉你结果如何。 它没有用。我怀疑服务器配置有问题。 php.net/manual/en/session.configuration.php 可能是权限问题,请检查您的运行网络服务器的用户是否有权将文件写入 session.save_path。您还可以检查脚本执行时是否在会话保存路径中创建会话文件。 所有文件权限都OK。正在写入/读取文件,问题(当我更新问题时)是文件在每个脚本中以不同的方式编码。【参考方案2】:

我终于明白了。

正如我在问题中发布的那样,问题在于 session_handler 正在使用不同的编码编写 sess 文件。因此,这两个脚本都试图读取文件,但都无法正确读取变量。

我有一个 php.ini 文件,用于通过指令更改默认字符集

default_charset = "iso-8859-1"

我不得不使用这个指令,因为服务器管理员做了一些更改。我在根目录下创建了一个.user.ini 文件来使用ISO 编码,但是我忘记删除这个php.ini 文件了。

可能由于php.ini 文件只影响了其中一个脚本(另一个位于不同的文件夹中),字符集与编码/解码过程发生了冲突。所以我删除了那个指令,问题就消失了。

希望这个问题将来能对某人有所帮助。

【讨论】:

【参考方案3】:

尝试设置会话时间:

define("SESSION_TIME_EXPIRED",'172800');    
session_set_cookie_params(SESSION_TIME_EXPIRED); 
session_name('user');
session_start();

【讨论】:

【参考方案4】:

session_set_cookie_params(0, ...) 不创建立即过期的会话吗?

http://php.net/manual/en/function.session-set-cookie-params.php

【讨论】:

实际上值 0 会创建一个持续到浏览器关闭的会话。 php.net/manual/en/…【参考方案5】:

我遇到了同样的问题。 我正在使用自定义会话。 用这个

session_regenerate_id();

不是

session_regenerate_id(true);

在开始会话后使用它

【讨论】:

以上是关于jQuery POST 请求后 PHP 会话数据丢失的主要内容,如果未能解决你的问题,请参考以下文章

jquery 和 php ajax 会话

jQuery 和 ajax 在 PHP 中设置会话变量

详细解读Jquery的$.get(),$.post(),$.ajax(),$.getJSON()用法

ajax请求后php会话值被擦除

理解PHP中的会话控制

将 jQuery 数组传递给 PHP (POST)