【问题标题】:PHP - Can't add session variable even after session_startPHP - 即使在 session_start 之后也无法添加会话变量
【发布时间】:2014-12-18 21:25:07
【问题描述】:

大多数关于不添加会话变量的答案都以用户发现会话没有启动而告终。

我遇到了一个问题,即使在 session_start 之后,我也无法添加会话变量。

相关代码:

登录.php

<?php 
    require("../common.php"); 
    if(!empty($_SESSION['user'])) { 
        echo "true";
        header("Location: dashboard.php"); 
        die("Redirecting to dashboard.php"); 
    } 
    $submitted_username = ''; 
    if(!empty($_POST)) { 
        $info = " SELECT id, username, password, salt, email, access FROM users WHERE username = :username "; 
        $params = array( ':username' => $_POST['username'] ); 
        try { 
            $stmt = $db->prepare($info); 
            $result = $stmt->execute($params); 
        } catch(PDOException $ex)  { 
            die("Failed to run query"); 
        } 
        $login_ok = false; 
        $row = $stmt->fetch(); 
        if($row) { 
            $check_password = hash('sha256', $_POST['password'] . $row['salt']); 
            for($round = 0; $round < 65536; $round++)  { 
                $check_password = hash('sha256', $check_password . $row['salt']); 
            }  
            if($check_password === $row['password']) { 
                $login_ok = true; 
            } 
        } 
        if($login_ok) { 
            unset($row['salt']); 
            unset($row['password']); 
            $_SESSION['user'] = $row;
            $_SESSION['access'] = "1";
            header("Location: dashboard.php"); 
            session_write_close();
            die("Redirecting to: dashboard.php"); 
        }  else { 
echo "<div id=\"loginfail\" class=\"gradwin\">\n";
echo "  <p class=\"dark1\">LOGIN FAILURE</p>\n";
echo "</div>\n";
            $submitted_username = htmlentities($_POST['username'], ENT_QUOTES, 'UTF-8'); 
        } 
    } 
?> 
<div id="loginbox" class="gradwin">
    <p class="darktitle">HITS Login</p> 
    <form action="index.php" method="post" name="formLogin"> 
    <!-- fake fields for Chrome autofill... -->
    <input style="display:none" type="text" name="fakeusername"/>
    <input style="display:none" type="password" name="fakepassword"/>
        <p class="dark1">Username:</p>
        <input type="text" name="username" autocomplete="off"><br>
        <p class="dark1">Password:</p> 
        <input type="password" name="password" autocomplete="off"><br><br>
        <input type="submit" value="Login" name="loginForm"><br><br>
    </form> 
    <a class="dark" href="register.php">Register</a>
</div>

common.php

<?php 

    $username = "MYNAME"; 
    $password = "MYPASS"; 
    $host = "localhost"; 
    $dbname = "MYDB"; 
    $conn = new mysqli($host, $username, $password, $dbname);
    $options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'); 

    try { 
        $db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options); 
    } catch(PDOException $ex) { 
        die("Failed to connect to the database: " . $ex->getMessage()); 
    } 
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); 
    header('Content-Type: text/html; charset=utf-8'); 
    session_start(); 

我被重定向到dashboard.php 页面,所以我知道有一个会话已启动。 session_start 在 common.php 文件中。我已经放置...

echo '<pre>';
var_dump($_SESSION);
echo '</pre>';

...在dashboard.php 文件中。我可以看到所有相关的用户数据,但看不到访问数据。我的数组回显如下:

array(1) {
  ["user"]=>
  array(3) {
    ["id"]=>
    string(2) "11"
    ["username"]=>
    string(2) "ba"
    ["email"]=>
    string(9) "ba@ba.com"
  }
}

【问题讨论】:

  • session_start() 在哪里?这些文件是否在同一个(子)域上?
  • 通用文件在webroot之外,比我的login.php和dashboard.php文件高一级。
  • common.php 是什么样子的,你可能在那里手动设置了$_SESSION['user']
  • 你只是假设 session_start() 成功了。检查它的返回值。如果为假,则会话不会开始。

标签: php session


【解决方案1】:

您在调用 session_start() 之前发送的标头。 session_start() 必须在发送任何标头之前进行:

header('Content-Type: text/html; charset=utf-8'); 
session_start(); 

应该是

session_start(); 
header('Content-Type: text/html; charset=utf-8');

或者,更好的是,将其移至文件顶部。

【讨论】:

  • 我也是这么想的,但是if(!empty($_SESSION['user'])) { 和那里的标头重定向不起作用,或者他们会吗?
  • 它不应该工作。但我没有想法。我想看看他们是否对此提供反馈,以便我们确定。
  • 不幸的是,这并没有改变任何东西。我把它放在我的 common.php 文件的顶部以获得最佳实践。
【解决方案2】:

尝试在重定向/位置标头之前添加 session_write_close()。我注意到在某些情况下重定向会导致会话无法正确写入。

【讨论】:

    【解决方案3】:

    IIRC,调用die()exit() 将停止存储会话数据。将触发其他关闭函数和析构函数,但不会触发 session_write_close()

    您要么需要在die() 之前运行session_write_close(),要么重写该部分以不使用die()

    这里有更多信息。 https://bugs.php.net/bug.php?id=49462&edit=1

    【讨论】:

    • 我删除了 die 语句,因为 login.php 页面上没有什么可隐藏的。那仍然没有解决任何问题。我已经在上面扩展了我的代码 sn-p,所以希望现在有人能看到不寻常的东西。
    【解决方案4】:

    愚蠢的错误!!!

    我在服务器上有两个版本的 login.php 文件。一个叫做inc_login.php,我正在修改它。 index.php 正在查看另一个。我把它理顺了,一切都很好。

    其他人遇到不可能的问题,请注意:您可能正在做一些像我一样愚蠢的事情。

    【讨论】:

      【解决方案5】:

      你的代码在这里:

      if(!empty($_SESSION['user'])) {
          $_SESSION['access'] = "1";
          header("Location: dashboard.php"); 
          die("Redirecting to dashboard.php"); 
      } 
      

      我认为错误在于运行大括号内代码的 if 语句。只有当会话变量“用户”不为空时,您才启动代码运行,这非常好。但是,您从未为其设置变量,因此代码从未设置会话变量“访问”来存储输入 1,因此该数组正在转储空会话变量。

      试试这个:

      <?php 
      require("../common.php"); 
      
      
          if(empty($_SESSION['user'])) {
              $_SESSION['access'] = "1";
              header("Location: dashboard.php"); 
              die("Redirecting to dashboard.php"); 
          } 
      

      【讨论】:

        猜你喜欢
        • 2018-04-22
        • 2011-06-05
        • 2014-08-14
        • 2019-02-20
        • 1970-01-01
        • 2017-07-11
        • 1970-01-01
        • 2014-03-22
        • 2018-11-25
        相关资源
        最近更新 更多