首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >登录后无会话

登录后无会话
EN

Stack Overflow用户
提问于 2011-12-20 08:07:17
回答 3查看 414关注 0票数 0

我有个奇怪的问题。我已经用PHP创建了一个可以正常工作的登录页面。我决定在用户点击登录页面时销毁所有会话。但是,通过这样做,用户永远不会登录。我看不出有什么问题。

登录页面

代码语言:javascript
复制
<?php
session_start();

// Destroy any active session
session_destroy();

// Regenerate Session ID
session_regenerate_id(true);

if($_SERVER['REQUEST_METHOD'] == 'POST') {
    $username = $_POST['username'];
    $password = md5($_POST['password']);

    if(strlen($username) > 12) {
        header('Location: index.php');
    }

    try {
        $dbh = new PDO('mysql:dbname=addcovers;host=127.0.0.1', 'root', '');
        $sth = $dbh->prepare('SELECT display_name FROM users WHERE username = :username && password = :password');
        $sth->bindParam(':username', $username, PDO::PARAM_STR, 12);
        $sth->bindParam(':password', $password, PDO::PARAM_STR, 32);
        $sth->execute();
        $result = $sth->fetch(PDO::FETCH_OBJ);

        if($result) {
            $_SESSION['logged_in'] = true;
            $_SESSION['user'] = $result->display_name;
            header('Location: index.php');
        }
    } catch (PDOException $e) {
        // DEBUG: echo 'Connection failed: ' . $e->getMessage();
    }

}
?>
<!DOCTYLE html>
<html>
<head>
    <title></title>

    <link rel="stylesheet" href="css/reset.css" type="text/css" media="all">
    <link rel="stylesheet" href="css/base.css" type="text/css" media="all">
</head>

<body id="admin-login">
    <form action="login.php" method="POST">
        <fieldset>
            <div><label for="username">Username</label><input type="text" name="username" maxlength="12"></div>
            <div><label for="password">Password</label><input type="password" name="password"></div>
            <button type="submit">Admin Login</button>
        </fieldset>
    </form>
</body>

管理页面

代码语言:javascript
复制
<?php
session_start();

if(!isset($_SESSION['logged_in'])) header('Location: login.php');

echo 'Welcome ' . $_SESSION['user'];

?>

如果我从登录页面中删除session_destroy,它可以正常工作。目前,即使凭据是正确的,用户也会继续访问登录页面。

EN

回答 3

Stack Overflow用户

发布于 2011-12-20 08:20:24

您不能在更改会话id后立即执行标头位置重定向。您正在创建一个新的会话id,但是新的会话id不会被发送回浏览器,因为您执行了重定向。所以浏览器继续使用旧的会话id (它是空的,因为您已经销毁了它)。

注意PHP的文档说明:

即使启用了session.use_trans_sid,也不会通过Location标头传递

会话ID。它必须使用SID常量手动传递。

至于如何修复它,我不确定。快速搜索不会显示太多内容。也许您需要读取SID常量并手动将新会话id的正确标头发送回浏览器,作为重定向的一部分。

或者,您可以显示其中一条“您已登录”的消息,然后使用javascript或<meta>标记重定向到index.php

还要注意这一行代码:

代码语言:javascript
复制
header('Location: index.php');

将仅发送当前请求的头响应,该请求将发送到login.php。它仍然会继续执行你的脚本。通常,您应该始终在发送该标头后退出:

代码语言:javascript
复制
header('Location: index.php');
exit;

我不认为这会导致你的bug,但你应该修复它。

票数 1
EN

Stack Overflow用户

发布于 2011-12-20 08:16:02

如果在index.php中注释掉这一行呢?

代码语言:javascript
复制
if(!isset($_SESSION['logged_in'])) header('Location: login.php');

(即:index.php是否在会话中看到内容?也可以通过打印var_export($_SESSION);进行尝试)

我记得PHP会话给出了一些明显的随机问题,这取决于$_SESSION不是全局的;但您的代码似乎在全局范围内。我说的对吗?

票数 0
EN

Stack Overflow用户

发布于 2011-12-20 08:16:32

在用户登录之前调用session_destroy没有任何好处--即使您真的想这样做,这也不是正确的方法。

session_destroy的文档说,在调用它之后,

若要再次使用会话变量,必须调用session_start()

您不需要这样做,所以您稍后设置的会话变量不会“卡住”,管理页面会重定向回login。

如果您确实希望完全销毁用户会话,则:

  1. 遵循文档中的示例:销毁会话,重新生成id,取消设置cookie.仅当用户通过用户名/密码检查时才执行此操作,而不是在为新会话设置任何会话变量之前再次执行unconditionally.
  2. Call
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8569257

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档