You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP会话无法持久化求助:登录状态跳转后丢失

解决PHP会话持久化与循环重定向问题

核心问题分析

你的代码存在三个关键问题导致会话无法持久化和循环重定向:

  • 登录状态判断逻辑混乱,变量作用域错误导致无法识别已登录状态
  • isGranted函数未处理会话变量不存在的情况
  • 业务逻辑与视图输出耦合,导致页面结构混乱

具体修复方案

1. 修复isGranted函数

确保函数安全判断会话状态,避免未定义索引警告:

function isGranted() {
    // 先检查变量是否存在,再判断值是否为true
    return isset($_SESSION['granted']) && $_SESSION['granted'] === true;
}

2. 重构页面逻辑,统一状态判断

将登录状态检查放在页面最前端,分离业务逻辑和视图渲染:

  • 先处理登出请求
  • 再判断是否已登录:已登录则展示内容,未登录则处理登录请求或显示表单

3. 修复变量作用域与参数错误

页面底部的判断条件中,$_POST['username']应为$_POST['userName'],且$result是函数内部变量,外部无法访问,需完全重构这部分逻辑。

修改后的完整代码

<?php
session_start();

// 数据库常量(请自行补充)
if ($_SERVER['HTTP_HOST'] == 'localhost') {
    define('HOST', 'localhost');
    define('USER', 'your_db_user');
    define('PASS', 'your_db_pass');
    define('DB', 'your_db_name');
} else {
    // 线上环境常量
    define('HOST', 'your_prod_host');
    define('USER', 'your_prod_user');
    define('PASS', 'your_prod_pass');
    define('DB', 'your_prod_db');
}

// 连接数据库
function connectToDatabase() {
    $conn = mysqli_connect(HOST, USER, PASS, DB);
    if (!$conn) {
        die("Connection failed: " . mysqli_connect_error());
    }
    return $conn;
}

// 验证用户名密码,返回登录状态
function checkUserNameAndPassword($username, $password) {
    $conn = connectToDatabase();
    // 建议使用预处理语句避免SQL注入(即使是作业也养成好习惯)
    $sql = "SELECT * FROM users WHERE username = ? AND password = ?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("ss", $username, $password);
    $stmt->execute();
    $result = $stmt->get_result();
    
    $isValid = $result->num_rows == 1;
    if ($isValid) {
        $_SESSION['granted'] = true;
        setcookie('name', $username, time() + 3600);
    }
    
    $stmt->close();
    $conn->close();
    return $isValid;
}

// 安全判断登录状态
function isGranted() {
    return isset($_SESSION['granted']) && $_SESSION['granted'] === true;
}

// 处理登出
if (isset($_GET['logout']) && $_GET['logout'] == 'true') {
    $_SESSION = array();
    session_destroy();
    header("Location: index.php");
    exit;
}

// 处理登录请求
$loginSuccess = false;
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    if (isset($_POST['userName']) && isset($_POST['password'])) {
        $username = $_POST['userName'];
        $password = $_POST['password'];
        $loginSuccess = checkUserNameAndPassword($username, $password);
    }
}
?>

<!doctype html>
<html lang="en">
<head>
    <title>Insecure Passwords</title>
    <link rel="stylesheet" href="css/style.css" type="text/css">
</head>
<body>
    <?php if (isGranted() || $loginSuccess): ?>
        <!-- 已登录状态 -->
        <div class="navbar">
            <a href=".">Home</a>
            <a href="?logout=true">Logout</a>
        </div>
        <div class="form">
            <div class="access">ACCESS GRANTED</div>
        </div>
        <div class="table">
            <table>
                <tr>
                    <th class="title">Agent</th><th class="title">Code Name</th>
                </tr>
                <?php
                $fileContents = file_get_contents("includes/fbi.txt");
                $lines = explode('||>><<||', $fileContents);
                foreach ($lines as $line) {
                    $pair = explode(',', $line);
                    if (count($pair) < 2) continue; // 跳过无效行
                    $agent = ucfirst($pair[0]);
                    $codename = $pair[1];
                    
                    // 格式化代号
                    if (strpos($codename, ' ') !== false) {
                        $words = explode(' ', $codename);
                        foreach ($words as &$word) {
                            $word = ucfirst($word);
                        }
                        $codename = implode(' ', $words);
                    } else {
                        $codename = ucfirst($codename);
                    }
                    echo "<tr><td>{$agent}</td><td>{$codename}</td></tr>";
                }
                ?>
            </table>
        </div>
    <?php else: ?>
        <!-- 未登录状态 -->
        <div class="form">
            <?php if ($_SERVER['REQUEST_METHOD'] == 'POST'): ?>
                <div class="access">ACCESS DENIED<br></div>
                <p>Please enter valid credentials.</p>
            <?php endif; ?>
            <form method="post" name="logIn">
                <input type="text" placeholder="User Name" name="userName"><br><br>
                <input type="password" placeholder="Password" name="password"><br><br>
                <div class="submit">
                    <input type="submit" name="sub-button">
                    <input type="reset" name="reset-button">
                </div>
            </form>
        </div>
    <?php endif; ?>
</body>
</html>

关键修改说明

  • 统一状态判断:通过isGranted()函数在视图中统一判断登录状态,确保刷新或跳转后能正确识别会话
  • 分离逻辑与视图:将登录验证的业务逻辑和页面渲染分离,避免函数内直接输出HTML导致的结构混乱
  • 修复变量问题:修正POST参数名错误,解决函数内部变量无法在外部访问的问题
  • 安全处理会话:isGranted()先检查会话变量是否存在,避免未定义索引警告
  • 优化SQL查询:使用预处理语句(可选,但建议养成习惯)

内容的提问来源于stack exchange,提问作者WastelandSniper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 03:35:01