PHP同时使用Session和Cookie实现用户登录状态管理

认真发呆
认真发呆
发布时间:2026-10-14| 3人浏览过
原创

在Web开发中,同时利用Server端的Session和Client端的Cookie是维持用户登录状态的经典方案。Session负责短期内的会话追踪,而Cookie可用于长期保留登录凭证。本文将详细解析如何通过PHP代码结合两者,完成从数据库校验、状态设置到安全注销的完整流程。

实现原理与准备

Session数据存储在服务器端,安全性较高但依赖用户的浏览器支持且默认有效期较短;Cookie存储在客户端,便于实现“自动登录”,但需防范篡改风险。本方案的核心逻辑如下:

  1. 登录时:后端验证用户名密码无误后,同时在当前会话(Session)和浏览器(Cookie)中写入用户标识。
  2. 访问其他页面时:优先读取Session。若Session失效(如关闭浏览器),则尝试读取Cookie并恢复Session状态。
  3. 注销时:同步清除服务器端Session数据和客户端Cookie,重定向至登录页。

在开始之前,请确保你的环境已安装PHP并配置好MySQL数据库。为了演示,我们需要一个包含用户信息的表结构(通常包含 user_id, username, password)。请注意,生产环境中应使用 password_hash() 而非简单的SHA加密,下文代码仅用于展示逻辑结构。

第1步:配置数据库连接信息

创建一个独立的配置文件 connectvars.php,集中管理数据库连接参数。这样可以在后续多个页面中复用该配置,避免硬编码。

<?php
define('DB_HOST', 'localhost'); // 建议使用 localhost 或 127.0.0.1
define('DB_USER', 'root');      // 根据你的数据库用户名修改
define('DB_PASSWORD', '');       // 建议移除默认弱密码
define('DB_NAME', 'your_database_name'); // 替换为你的实际库名
?>

第2步:构建登录页面 (logIn.php)

这是入口页面,主要处理POST请求提交的用户凭据,并进行服务端验证。

操作入口与动作

  1. 初始化会话:调用 session_start() 启动Session机制。
  2. 检查登录状态:如果 $_SESSION['user_id'] 已存在,说明用户已登录,直接跳转到欢迎页面。
  3. 处理登录表单:当检测到 $_POST['submit'] 时,连接数据库查询用户。
  4. 设置双重凭证:验证成功后,向 $_SESSION 和 setcookie() 分别写入用户ID和用户名。
代码如下:
<?php
// 引入数据库配置
require_once 'connectvars.php';

// 开启会话
session_start();
$error_msg = "";

// 若未登录且提交了表单
if(!isset($_SESSION['user_id']) && isset($_POST['submit'])){
    $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
    
    // 获取并转义输入,防止SQL注入
    $user_username = mysqli_real_escape_string($dbc, trim($_POST['username']));
    $user_password = mysqli_real_escape_string($dbc, trim($_POST['password']));
    
    if(!empty($user_username) && !empty($user_password)){
        // 注意:实际项目中请使用 password_verify() 进行哈希比对
        $query = "SELECT user_id, username FROM users WHERE username = '$user_username' AND password = SHA('$user_password')";
        $data = mysqli_query($dbc, $query);
        
        // 如果找到唯一匹配记录
        if(mysqli_num_rows($data) == 1){
            $row = mysqli_fetch_array($data);
            
            // 1. 设置 Session(短期/当前会话有效)
            $_SESSION['user_id'] = $row['user_id'];
            $_SESSION['username'] = $row['username'];
            
            // 2. 设置 Cookie(长期有效,例如30天)
            // 路径设为 '/' 确保站点所有目录可访问
            setcookie('user_id', $row['user_id'], time() + (60*60*24*30), '/');
            setcookie('username', $row['username'], time() + (60*60*24*30), '/');
            
            // 重定向到已登录页面
            header('Location: loged.php');
            exit;
        } else {
            $error_msg = '用户名或密码错误!';
        }
    } else {
        $error_msg = '请输入有效的用户名和密码!';
    }
    mysqli_close($dbc); // 关闭连接
} else if (isset($_SESSION['user_id'])) {
    // 如果已经登录,直接跳转
    header('Location: loged.php');
    exit;
}
?>
<html>
<head><title>登录</title></head>
<body>
    <h3>用户登录</h3>
    <p style="color:red"></p>
    <form method="post" action="">
        Username: <input type="text" name="username" /><br/>
        Password: <input type="password" name="password" /><br/>
        <input type="submit" value="Log In" name="submit" />
    </form>
</body>
</html>

登录表单渲染后的效果如图所示:

第3步:创建已登录主页 (loged.php)

此页面作为登录后看到的受保护内容。关键逻辑在于:优先使用Session,若Session丢失则利用Cookie恢复Session。

状态恢复逻辑

  1. 启动Session:必须首先调用 session_start()。
  2. 回补机制:如果 !isset($_SESSION['user_id']),检查是否存在有效的Cookie。如果存在,将Cookie值赋给Session变量,从而重新激活服务器端会话。
  3. 显示内容:确认登录状态后,显示欢迎信息和注销链接。
代码如下:
<?php
// 开启会话
session_start();

// 核心步骤:如果Session中没有用户ID,尝试从Cookie中恢复
if(!isset($_SESSION['user_id'])){
    if(isset($_COOKIE['user_id']) && isset($_COOKIE['username'])){
        $_SESSION['user_id'] = $_COOKIE['user_id'];
        $_SESSION['username'] = $_COOKIE['username'];
    }
}

// 检查最终登录状态
if(isset($_SESSION['username'])){
    echo '<p>欢迎回来, ' . htmlspecialchars($_SESSION['username']) . '!</p>';
    echo '<a href="logOut.php">注销登录</a>';
} else {
    // 如果既没有Session也没有Cookie,重定向回登录页
    header('Location: logIn.php');
}
?>
<html>
<head><title>已登录</title></head>
<body>
    <h3>登录成功页面</h3>
</body>
</html>

用户登录成功后的界面示例:

第4步:实现安全注销 (logOut.php)

注销不仅仅是跳转,更重要的是破坏会话状态。必须同时清除服务器端的Session数据和客户端的Cookie。

清除操作顺序

  1. 启动Session:以便访问 $_SESSION 数组。
  2. 清除Session数据:将 $_SESSION 赋值为空数组,并调用 session_destroy() 销毁服务器端会话文件。
  3. 删除Session Cookie:设置旧的Session Cookie过期时间为过去时间(如 -3600秒)。
  4. 删除自定义Cookie:同样将之前设置的 user_id 和 username Cookie设置为过去时间。
  5. 重定向:跳回登录页面。
代码如下:
<?php
session_start();

// 1. 清除服务器端Session数据
if(isset($_SESSION)){
    $_SESSION = array();
    
    // 2. 删除与Session相关的Cookie
    if(isset($_COOKIE[session_name()])) {
        setcookie(session_name(), '', time()-3600, '/');
    }
}

// 3. 销毁Session
session_destroy();

// 4. 清除我们自定义的用户标识Cookie
setcookie('user_id', '', time()-3600, '/');
setcookie('username', '', time()-3600, '/');

// 5. 重定向到登录页
header('Location: logIn.php');
exit;
?>

注意事项与排错

  • Header警告:如果在 session_start() 或 header() 输出任何HTML或空格,会导致 "Headers already sent" 错误。请确保PHP标签
  • Cookie域名:如果设置了特定域名导致Cookie无法读写,请检查 domain 参数或留空以使用当前域。
  • 安全性建议:原示例中使用SHA()加密存储密码不符合现代安全标准。请务必在生产环境中使用 password_hash() 生成哈希,并使用 password_verify() 进行验证。此外,建议在登录成功后使用 session_regenerate_id(true) 防止会话固定攻击。

总结

通过上述步骤,我们实现了基于Session和Cookie双重机制的PHP用户登录系统。Session保障了交互过程中的安全性与实时性,而Cookie提供了便捷的“记住我”体验。关键在于理解两者的生命周期差异,并在注销时彻底清理两边数据。以上就是PHP中同时使用Session和Cookie来保存用户登录信息的详细内容,更多关于PHP会话管理的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。