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

PHP+MySQL登录系统CSRF令牌验证失败问题求助

问题分析与解决方案

核心问题定位

  • 重复生成CSRF令牌:访问index.php和login.php时分别生成令牌,导致登录提交的令牌与当前会话绑定的令牌不匹配
  • 首页空令牌记录:index.php的CSRF生成逻辑存在漏洞,未生成有效令牌或未关联会话ID
  • Invalid CSRF Token错误:令牌不匹配、会话关联失效、验证逻辑错误三者共同或单独导致

分步排查与修复

1. 统一CSRF令牌生成入口

移除index.php中的CSRF令牌生成代码,仅在**登录入口页面login.php**生成令牌,避免重复创建:

session_start();
// 仅当会话中无有效令牌时生成新令牌
if (!isset($_SESSION['csrf_token'])) {
    $csrf_token = bin2hex(random_bytes(32));
    $_SESSION['csrf_token'] = $csrf_token;
    // 存入数据库时绑定当前会话ID,避免空记录
    $stmt = $pdo->prepare("INSERT INTO csrf_tokens (token, session_id, created_at) VALUES (?, ?, NOW())");
    $stmt->execute([$csrf_token, session_id()]);
}

2. 修复空令牌记录问题

  • 彻底删除index.php中所有CSRF令牌生成逻辑,将令牌操作统一交由login.php处理
  • 检查csrf_tokens表结构,确保session_id字段长度足够存储PHP会话ID(建议设为50字符)

3. 修正CSRF验证逻辑

登录验证时需同时完成三重校验:

session_start();
// 校验请求中的令牌是否存在且与会话令牌一致
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
    die("Invalid CSRF Token");
}
// 校验数据库中令牌是否与当前会话绑定(防止会话劫持后的令牌复用)
$stmt = $pdo->prepare("SELECT * FROM csrf_tokens WHERE token = ? AND session_id = ?");
$stmt->execute([$_POST['csrf_token'], session_id()]);
if (!$stmt->fetch()) {
    die("Invalid CSRF Token");
}
// 验证通过后,删除已使用的令牌避免重复利用
$stmt = $pdo->prepare("DELETE FROM csrf_tokens WHERE token = ?");
$stmt->execute([$_POST['csrf_token']]);

4. 兼容“记住我”会话配置

确保会话有效期设置正确,且不会重置会话ID导致令牌关联失效:

session_set_cookie_params([
    'lifetime' => 30*24*60*60, // 30天有效期
    'path' => '/',
    'secure' => true, // HTTPS环境下启用
    'httponly' => true,
    'samesite' => 'Strict'
]);
session_start();

5. 调试方法

在login.php页面添加调试输出,确认令牌与会话的一致性:

echo "当前会话ID: " . session_id() . "<br>";
echo "当前CSRF令牌: " . $_SESSION['csrf_token'] . "<br>";

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 16:39:56