【问题标题】:PHP Session Data Not Being Stored未存储 PHP 会话数据
【发布时间】:2009-07-26 20:20:10
【问题描述】:

我正在制作一个登录系统,但是当用户登录时,它实际上并没有在会话中存储我希望它存储的任何数据。我什至检查了会话的文件,它是空的。我有 session_start();在所有页面上。我还能做错什么。这是两个主要页面的代码。

登录代码:

<?
if ($DEBUG == true) {
    error_reporting(E_ALL);
}
require "header.php";

require_once "dbinterface.php";
require_once "user.class.php";
require_once "config.inc.php";

$db = new db($DB['host'], $DB['user'], $DB['pass'], $DB['database']);

$u_result = $db->run("select user_id from users where user_name = '" . $db->escape($_POST['user_name']) . "'");

if ($u_result == false) {
    $url = 'Location: error.php?id=8';
    header($url);
}

if (count($u_result) < 1) {
    $url = 'Location: error.php?id=3';
    header($url);
}

$user = new user($u_result[0]['user_id']);

if ($user->match_password($_POST['pass']) == true) {
    $_SESSION['authenticated'] = true;
    $_SESSION['user_id'] = $u_result[0]['user_id'];
    $_SESSION['user'] = $user;
} else {
    $url = 'Location: error.php?id=4';
    header($url);
}
session_write_close();
header('Location: index.php');

?>

每个页面中包含的标题:

<?php
if (!session_start()) {
    $url = "Location: error.php?id=13";
    header($url);
}
?>

一点背景:

  • windows 7(也在 windows 上试过
  • 服务器 2008,但目前在 7) PHP
  • 存在 5 个本地托管问题
  • 每个人都存在问题
  • 浏览器

【问题讨论】:

  • 您需要将 session_start 放在第一个 php 文件的最顶部。
  • @MrHus:不正确。您只需要在向浏览器输出任何内容之前调用 session_start()。
  • 嗨,你解决过这个问题吗?我的回答是否指出了真正的错误?
  • 是的,deramon,你的答案是正确的。但是当我看到它时,我自己已经弄清楚了,所以已经自动接受了答案=/对不起。

标签: php session


【解决方案1】:

这里有一些建议(我真的不知道发生了什么和/或为什么;所以它们只是建议;也许有人会解决问题^^)。

首先,有几个问题:
(至少如果这些建议都不起作用,它们很重要)

  • 您使用的是哪个版本的 PHP/Apache?
  • 您使用的是 Windows 吗? Linux ?
  • 如果您在“生产”服务器上,您使用的是什么托管服务?也许它有什么特别之处?
  • 每个人都存在问题吗?
    • 您在浏览网站时是否总是出现问题?
    • 当您从其他浏览器访问该站点时,它是否仍然存在?
    • 从另一台计算机呢?
  • 如果在会话中设置数据的脚本末尾使用 var_dump($_SESSION); die; 之类的东西,它会提供什么?


第一个想法:如果您设置一些标头以禁用浏览器缓存怎么办?
例如这样的东西:

session_start();
header("Cache-control: private");


第二个想法(至少如果您在 Windows 上):您是否尝试禁用防病毒/防火墙?
是否在客户端浏览器中正确创建了会话 cookie?
如果您使用子域(或不使用):cookie 的域是否正常?它的有效期呢?


第三个想法:

  • 你说error_reporting 设置为E_ALL,这很好
  • display_errors 呢?是否设置为 On 以便显示错误?
  • PHP/Apache 的error_log 有什么有趣的地方吗?


另一个:您确定在session_start 之前绝对没有任何内容可以输出吗?甚至没有空格?


还有一个:您确定目录/文件的权限吗?

  • 在目录中写入权限意味着您可以创建新文件和/或删除旧文件。
    • 但是,如果我没记错的话,并不是说你可以修改它们
  • 要修改文件,您还需要对文件具有写权限
    • 实际上,您的网络服务器需要对这些文件具有写入权限 ^^

会话目录和创建的(空)文件的权限是什么?


我的想法开始用完了......如果运气好的话,也许其中一个会是正确的......或者帮助你找出正确的那个!

祝你好运!

【讨论】:

  • 缓存控制似乎没有什么不同。仍然有同样的问题。我已经在几个浏览器、几台计算机和几台服务器上尝试过,同样的问题。我还确保显示错误也已打开。不过感谢您的建议!
  • 哦 :-( 太糟糕了 :-( 如果您在不同的浏览器、不同的计算机和服务器上遇到同样的问题,那么您的代码毕竟可能存在某种问题......您能否制作一个包含完整源代码的存档,如果它不是很大/很难设置,那么我们可以尝试仔细看看?
【解决方案2】:

一个可能的原因是在 header('Location...') 语句之后继续执行。但是,您似乎希望它停止,因此您应该添加“退出;”重定向到error.php后。例如:

if ($u_result == false) {
    $url = 'Location: error.php?id=8';
    header($url);
    exit;
}

这也可能是您的问题的一部分,因为您从未访问 error.php 并查看错误代码。最后一行总是被执行:

header('Location: index.php');

而且由于 header() 的默认行为是替换现有的 headers,所以无论如何你总是去 index.php。

【讨论】:

    【解决方案3】:

    根据 PHP header() 文档中的评论,我相信您需要在文件底部执行以下操作。 header('Location: x'); 是使用header() 函数的特殊情况,如果在发出header() 调用之前会话没有时间写入,它可能会干扰会话传递。 session_write_close() 应该可以解决这个问题。

    ...    
    session_write_close();
    header('Location: index.php');
    

    【讨论】:

    • 在阅读完文档后,我认为这样做可以,但它似乎并没有改变任何东西。
    【解决方案4】:

    找不到 SessionID。我曾经遇到过这个问题,正在疯狂地创建会话,但没有存储任何内容。 (另外,请确保您对会话文件夹具有适当的写入权限,一旦遇到此类问题)

    你真正想做的是

    $sessid = session_start(); // 用于新会话的开始,并且

    session_start($sessid); // 在每次后续调用的开始请求中,直到使用 session_destroy() 销毁会话

    当然,在网页之间传递 $sessid 变量取决于您。我更喜欢使用 &sessid= 链接添加剂;>(这样我会立即知道什么时候出了差错;P)

    请记住,确保正确恢复会话的唯一方法是传递会话 ID。我知道它是可选的,并且在大多数系统上它应该是开箱即用的,但有时它就是不能,而且根本无法保证共享主机上的会话行为。

    作为一个提示,尝试将您的会话包装在一个具有 __set() 和 __get() 的“魔术”默认处理程序的类中,这可能会使您以后验证会话数据的工作更加轻松(__call() 处理程序是尤其是有用的)。并使该类的构造函数期望一个会话 id,其中 0(或 -1 或其他)是“开始新会话”,并确保如果没有明确设置 ID,它会发出错误 - 这会提醒你 @ 987654321@问题。

    ---------[编辑

    哦,我是否提到过 - 在一个有大量用户请求的共享环境中,不明确命名您的会话可能会导致渗透问题(一个用户以另一个用户身份登录)。在大多数情况下,这不会发生,但如果您的主机配置非常糟糕,不命名您的会话并依赖“默认行为”可能会同时导致多个灾难。 ;-)

    【讨论】:

    • Google 将会话 ID 保存在 url 中。
    • 手动传递会话 ID 确实不是一个好的解决方案。这就是会话 cookie 的用途。
    • 风险!出于安全原因,即使您必须在每个请求上重新生成会话 ID!
    【解决方案5】:

    远射但值得一提:
    是否正确配置 PHP 以处理会话?
    phpinfo() 的输出是什么?

    【讨论】:

      【解决方案6】:
      • 首先我建议使用

        error_reporting(E_ALL);

        在每个文件的开头

      • 其次,我认为问题在于您包含 2 个 session_start,而发生的情况是您可能没有跟踪您认为的相同 session_id。

      【讨论】:

      • 即使启用了 E_ALL 错误报告,它仍然不会吐出任何错误。使用 header() 函数,不是重定向到另一个页面吗?因为那不会使它有两个 session_starts。还是更像是在该位置包含其他页面以进行处理?
      • 两次调用session_start() 不会导致此问题。来自手册:“从 [4.3.3 版] 开始,在会话已经启动时调用 session_start() 将导致 E_NOTICE 级别的错误。此外,第二次会话启动将被忽略。”
      【解决方案7】:

      当 session_start() 不是页面上的第一行代码时,我看到了一些奇怪的问题。尝试将你的 session_start()s 移到你的 include 和 requires 之上,看看是否能解决它。

      【讨论】:

      • 唯一的问题是我需要包含'user.class.php';在 session_start() 之前,因为我在会话中存储了一个对象。这要求它在 session_start() 之前;我在想虽然那不是一个可行的选择。节省了很多查询。
      【解决方案8】:

      我必须同意 Jason 之前所说的。只需在登录脚本中的所有内容之前添加session_start(); 行。将它放在 session_start() 函数之后的任何地方,甚至不在标题中。

      所以像这样修改你的代码

      <?
      session_start();
      if ($DEBUG == true) {
          error_reporting(E_ALL);
      }
      

      接下来是您的其余代码...

      希望这能解决问题。

      【讨论】:

      • 因为他在会话中存储类对象,所以他需要在 session_start() 之前包含类定义。就个人而言,我将类对象转换为字符串,然后再存储到会话中。您可以将它们显式转换为 XML。
      • 嗯,抱歉我没有意识到这一点。
      【解决方案9】:

      检查包含的尾随行。 有时,关闭 ?> 后的换行符将被输出,并阻止创建会话。在我弄清楚之前,这让我很认真。

      【讨论】:

      • 很好,我以前也遇到过这个问题,但这次不是问题了=/
      【解决方案10】:

      我已经测试了代码,甚至复制了你的 ini 设置。

      我做了一些简单的对象来替换 db 和 user。 并且因为daremon 所说的,如果与 user 和 db 相关的任何检查失败,它仍然会显示一个空的索引页(我的测试索引打印了 $_SESSION 超全局的内容)。

      那么,错误是否可能在类 db 或 user 中?你测试过那些吗? 要查看问题是否出在这些类上,就像 Daremon 所说的那样,在每个标头调用之后添加 exit 很简单。

      【讨论】:

        【解决方案11】:

        确保您的 session.save_dir 设置正确。如果您在类似 Media Temple 的地方托管在 home/####/domains/html 中,则它可能没有正确设置并且不会被保存。

        【讨论】:

        • 好点,但会话文件是 empty(而不是不存在)让我认为在这种情况下这不是问题。
        【解决方案12】:

        似乎没有设置 sessionID cookie

        【讨论】:

          【解决方案13】:

          查看您的 php.ini 设置。特别是,如果您手动执行session_start(),您希望将session.auto_start 设置为0。如果您依赖会话 cookie 或透明 URL 重写,您还需要 session.use_cookies=1 和/或 session.use_trans_sid=1。

          【讨论】:

          • session.auto_start 为 0。 session.use_cookies 为 1 且 session.use_trans_sid = 0
          【解决方案14】:

          首先:您托管的 PHP 版本是什么?

          在 PHP 版本 session_start() 将始终返回 TRUE,即使启动会话失败。 (见changelog。)


          第二:你试过了吗

          require_once("header.php");
          

          第三:您应该隔离问题。试试下面的

          • 创建一个名为 session_test.php 的新文件,其中包含:

            if( isset($SESSION['garbage']) && !empty($SESSION['garbage']) ) { echo 'Session data: ' . $SESSION['garbage']; } else { $SESSION['garbage'] = 'I like cake'; echo 'Session data written'; } ?>
          • 在浏览器中访问 http://:/session_test.php

          • 如果刷新页面会发生什么? (A.k.a:您的会话现在有效吗?)

          这将确保问题出在 php/apache|IIS 组合中,而不是在所有其他代码中。

          【讨论】:

            【解决方案15】:

            这听起来不像是您的问题的原因,但由于您还没有找到解决方案,您不妨检查一下您的主机是否使用负载平衡而不同步会话数据。这意味着您的用户可能会针对每个请求被发送到不同的服务器,除非会话数据目录在所有这些服务器上共享,否则您的会话数据将会丢失。

            这里可能不是这样,但前段时间让我很头疼,所以我发布它以防万一。

            【讨论】:

              【解决方案16】:

              去这个网站下载完成的登录系统(很棒的教程网站!),它和你的一样!

              http://net.tutsplus.com/videos/screencasts/how-to-build-a-login-system-for-a-simple-website/

              它可能无法回答您的会话问题,但以几乎相同的方式解决了主题;D

              【讨论】:

                【解决方案17】:

                我遇到了同样的问题。我的解决方案与这里的其他解决方案有点不同。在我的php.ini 文件中,我有这个设置register_globals=On。

                在我的代码中假设我有一个$_SESSION['user'],后来在我的代码中分配了一些东西给$user,它实际上是用我分配给$user的任何东西替换了我的$_SESSION['user']信息。

                所以要么确保register_globals 已关闭,要么更改您的变量名称。 =D

                【讨论】:

                  【解决方案18】:

                  磁盘空间也可能是问题之一,记得检查你的磁盘空间,如果它已满则无法写入。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-09-11
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2010-09-14
                    • 1970-01-01
                    • 2013-06-10
                    相关资源
                    最近更新 更多