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

PHP站点如何设置已登录用户的会话有效期,实现长期免登录

安全风险前置说明

  • 直接把原生PHP会话有效期设为1年首先会面临两个核心安全问题:
    • 会话ID泄露风险被无限放大:一旦用户的会话ID被窃取(比如公共设备未登出、XSS攻击、网络窃听),攻击者可以在一整年的时间里冒用用户身份
    • 服务端会话存储压力陡增:所有历史会话数据都会保留1年,就算用户早就不用你的站点了,数据也不会自动清理
      因此不建议直接修改原生session的全局有效期,更推荐做独立的「记住我」长效登录机制,和短期会话分离,兼顾体验和安全。

具体实现方案

方案1:快速调整原生Session配置(仅适合极小范围内部使用的站点)

如果你的站点确实只有个位数授权用户,且所有用户都使用私有设备,不想做复杂改造,可以直接调整php.ini或者运行时的session配置:

// 放在session_start()之前调用
// 设置会话Cookie的有效期为1年,单位是秒
ini_set('session.cookie_lifetime', 365 * 24 * 60 * 60);
// 服务端会话垃圾回收的最大生命周期也设为1年
ini_set('session.gc_maxlifetime', 365 * 24 * 60 * 60);
// 可选:固定会话Cookie的有效域和路径,避免异常失效
ini_set('session.cookie_path', '/');
ini_set('session.cookie_domain', $_SERVER['HTTP_HOST']);
// 开启HttpOnly避免XSS窃取会话Cookie,开启Secure如果你的站点用HTTPS
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on');

session_start();

注意:这个方案所有访问用户的会话都会变成1年有效期,包括未登录的访客,会产生大量垃圾会话数据,只适合极端小范围场景使用。

方案2:独立记住我Token机制(推荐)

不要把长效登录和原生会话绑定,原生会话还是保持短有效期(比如24小时),额外做长效Token实现免登,逻辑如下:

  1. 用户登录勾选「记住我」(或者默认勾选)时,生成一个高熵随机的remember_token,同时生成一个过期时间为1年的时间戳
  2. 把remember_token、对应用户ID、过期时间存入你的用户表或者独立的记住我表,Token建议做哈希存储(不要存明文,防止数据库泄露后被冒用)
  3. 给用户浏览器设置一个有效期1年的Cookie,存储用户ID和明文的remember_token
  4. 每次用户访问站点时,如果原生会话已经过期,就检测Cookie里的记住我信息:
    • 先校验Cookie里的用户ID对应的数据库存储的Token哈希,和Cookie里的Token哈希是否匹配
    • 校验Token是否在有效期内
    • 校验通过就自动为用户创建新的短期会话,实现免登,同时可以轮换生成新的Token,替换旧的Token和Cookie

示例核心代码:

// 用户登录成功后的记住我逻辑
if ($remember_me_checked) {
    // 生成32位高熵随机Token
    $remember_token = bin2hex(random_bytes(16));
    // 哈希后存数据库
    $hashed_token = password_hash($remember_token, PASSWORD_DEFAULT);
    $expire_at = time() + 365 * 24 * 60 * 60;
    // 写入数据库,这里替换成你自己的数据库操作
    $db->query("UPDATE users SET remember_token = ?, remember_token_expire = ? WHERE id = ?", [$hashed_token, $expire_at, $user_id]);
    // 设置Cookie
    setcookie(
        'remember_me',
        $user_id . '|' . $remember_token,
        $expire_at,
        '/',
        $_SERVER['HTTP_HOST'],
        isset($_SERVER['HTTPS']),
        true // HttpOnly
    );
}

// 会话过期后的自动登录逻辑
if (!isset($_SESSION['user_id']) && isset($_COOKIE['remember_me'])) {
    list($user_id, $remember_token) = explode('|', $_COOKIE['remember_me'], 2);
    // 查数据库对应用户的Token
    $user = $db->query("SELECT * FROM users WHERE id = ?", [$user_id])->fetch();
    if ($user && password_verify($remember_token, $user['remember_token']) && $user['remember_token_expire'] > time()) {
        // 校验通过,自动登录
        $_SESSION['user_id'] = $user_id;
        // 可选:轮换Token,提升安全性
        $new_token = bin2hex(random_bytes(16));
        $new_hashed = password_hash($new_token, PASSWORD_DEFAULT);
        $new_expire = time() + 365 * 24 * 60 * 60;
        $db->query("UPDATE users SET remember_token = ?, remember_token_expire = ? WHERE id = ?", [$new_hashed, $new_expire, $user_id]);
        setcookie('remember_me', $user_id . '|' . $new_token, $new_expire, '/', $_SERVER['HTTP_HOST'], isset($_SERVER['HTTPS']), true);
    } else {
        // 校验失败,清除无效Cookie
        setcookie('remember_me', '', time() - 3600, '/', $_SERVER['HTTP_HOST']);
    }
}

额外安全建议

  • 所有站点必须启用HTTPS,避免Cookie在传输过程中被窃听
  • 所有登录相关的Cookie都必须开启HttpOnly属性,防止XSS攻击窃取
  • 可以给记住我Token增加权限限制:比如涉及敏感操作(修改密码、删除数据)的时候,还是要求用户重新输入密码验证
  • 用户修改密码、主动登出的时候,要同步清除数据库里的记住我Token和对应的Cookie
  • 如果是多设备登录场景,建议做独立的记住我表,每个设备单独存Token,用户可以在后台手动吊销指定设备的登录权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:36:03