【问题标题】:Strange PHP Session behavior奇怪的 PHP 会话行为
【发布时间】:2011-08-13 16:38:15
【问题描述】:

我对某些会话变量的奇怪行为感到困惑。特别是“令牌”变量。

这就是我在 index.php 中创建它的方式:

<?php
session_start();
$_SESSION['token'] = sha1(rand(7451, 98632)); // Lets name it "something"
?>

然后我使用 AJAX 进行 POST 并将该变量传递给另一个脚本 ajax_io.php:

ajax_io.php里面:

<?php
session_start();
if($_POST['token'] != $_SESSION['token']) die('Horribly');
?>

我的检查总是“死掉”,虽然 index.php 中的 javascript AJAX 帖子正确传递了令牌,但 ajax_io.php 中的 $_SESSION['token'] 与 index.php 中创建的不同.

例如在 ajax_io.php 中:

The $_POST['token'] appears as "something"
but,
$_SESSION['token'] appears as "something else"

这就像 AJAX 帖子请求 index.php(以某种方式)创建另一个令牌,然后请求 ajax_io.php 执行请求的功能。

这里是 Javascript AJAX 请求:

var token = '<?php echo $the_token; ?>';    
$.post("ajax_io.php", {
        token: token
    }, function(data) {
        // Do something with data
    });

更新

我没有提到,在真正的脚本中,有一个 foreach 循环,而那个循环是造成问题的原因。它以某种方式在每个循环上用新生成的一个新生成的变量重写了 php 令牌变量,但脚本保留了用于设置 javascript 变量的原始值。

$the_token = sha1(mt_rand(10, 100));
$_SESSION['tokens'][] = $the_token; // Notice the multidimensional array here

foreach(somethin) :
// do something other than setting any session variable
endforeach;
print_r( $_SESSION );

输出:

Array (
[tokens] => array (
[0] => b19477cb038d6e0f588b6631c1686c8e246b82d5 // The real one created at the beginning of the script
[1] => 51e57c94bfd5c81b11e8c48dc8002b1162f4cd84
[2] => 084c881c074678218a4394524f60d3867da84cb3
)
)

在这个脚本上,如果我回显 $_SESSION,我会得到 N 个令牌,例如 3 个。但只有第一个是由我的脚本物理创建的,另外 2 个是由循环创建的。我浏览了整个循环脚本,但没有发现任何设置任何类型的变量到 SESSSION。

【问题讨论】:

  • 您是否正在检查以确保在页面加载时不会覆盖 $_SESSION 令牌?
  • 在 index.php 文件中只有一次出现 $_SESSION['token'] = "something"。
  • 好吧,现在有更奇怪的东西了。这似乎与浏览器有关。在 Firefox 上,如果我移位刷新页面 (index.php),则新令牌与 ajax_io.php 从会话中获取的令牌不匹配。在 Chrome 上,使用正常刷新 (F5) 或 shift-refresh 或 Ctrl+R。 2 个令牌从不匹配。在 Opera 上它工作得很好。
  • 什么是$the_token?为什么不直接回显实际的会话值?
  • 实际的随机令牌存储在一个名为 $the_token 的变量中,我将其传递给会话,如下所示: $_SESSION['token'] = $the_token;然后像这样进入javascript变量: var token = '';

标签: php javascript jquery ajax session


【解决方案1】:

你只是逻辑不好。不要每次都检查令牌。当你这样做时,它会覆盖它。只需根据需要生成它,而不是每次都生成。

$_SESSION['token'] = (empty($_SESSION['token'])) ? gen_new_token() : $_SESSION['token'];

你可以存储时间,它的有效期等等。

【讨论】:

  • 逻辑有效,我在脚本中指出了一个问题点。它在 While 循环中,只是一个简单的回显语句,当我从脚本中注释回显时,应用程序按预期运行。这可能是某种错误......因为该 echo 语句从数据库中打印一个 LONGTEXT,仅此而已。
【解决方案2】:

尝试将.post 更改为.ajax同步,然后告诉我们会发生什么。请发布脚本的准系统版本,因为您发布的内容正常,问题可能是其他地方的逻辑细节。

【讨论】:

  • WHILE 循环中有一条 ECHO 语句以某种方式触发了一个新的 SHA1 字符串。 .ajax 做同样的事情。我第一次使用 .ajax。
  • 好吧,一个 echo 语句不能触发它(除非它发生在 session_start() 之前)。所以,错误发生了这就是为什么你应该发布一个精简版本的代码,这样有人可以指出错误发生的位置。
【解决方案3】:

我不能从脚本中删除太多来发布代码,逻辑与原始帖子相同,WHILE 循环有大约 50-60 行代码。

我刚刚发现更多。浏览器似乎不止一次地请求 index.php 文件。

127.0.0.1 - - [14/Aug/2011:19:38:40 +0300] "GET /cmdownloads/index.php?itsme=petsoukos HTTP/1.1" 200 11919 127.0.0.1 - - [14/Aug/2011:19:38:40 +0300] “GET /cmdownloads/js/jquery-1.6.1.min.js HTTP/1.1”304 - 127.0.0.1 - - [14/Aug/2011:19:38:40 +0300] “GET /cmdownloads/js/jquery-ui-1.8.13.custom.min.js HTTP/1.1”304 - 127.0.0.1 - - [14/Aug/2011:19:38:40 +0300] “GET /cmdownloads/css/style.css HTTP/1.1”304 - 127.0.0.1 - - [14/Aug/2011:19:38:40 +0300] “GET /cmdownloads/js/script.js HTTP/1.1”304 - 127.0.0.1 - - [14/Aug/2011:19:38:40 +0300] “GET /cmdownloads/img/overlay.png HTTP/1.1”304 - 127.0.0.1 - - [14/Aug/2011:19:38:40 +0300] "GET /cmdownloads/index.php?itsme=petsoukos HTTP/1.1" 200 11980 127.0.0.1 - - [14/Aug/2011:19:38:40 +0300] "GET /favicon.ico HTTP/1.1" 404 209

用户正在刷新页面,但另一个...?找不到该请求的来源。

【讨论】:

  • 这太令人沮丧了,我已经将整个项目转换为 Codeigniter 并且在那里发生了同样的事情。到目前为止,我的结论是:它与浏览器相关,因为 Opera 按预期工作。
【解决方案4】:

发现双重请求的原因是foreach循环内渲染文本上的IMG标签。该标签有一个空的 src 参数,它在后台触发了一个请求。该请求正在刷新生成的密钥,但由于它在后台,前端部分没有获取新密钥。愚蠢的问题。

这个问题现在已经解决了。 (希望)

【讨论】:

    猜你喜欢
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 2014-03-03
    • 2017-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多