本地Email Verification正常,部署后提示Invalid token或过期问题求助
邮件验证功能在本地localhost环境运行正常,但部署到服务器后失效。用户点击邮件中的“验证邮箱”链接时,始终提示“无效令牌或令牌已过期”。数据库连接的用户名、密码、数据库名及服务器地址均与托管商提供的一致,相关代码如下:
<?php include 'db_connection.php'; // 检查URL中是否提供了令牌 if (isset($_GET['token'])) { $token = $_GET['token']; // 准备SQL语句,根据令牌获取关联邮箱 $stmt = $connection->prepare("SELECT email FROM email_verification WHERE token = ?"); $stmt->bind_param("s", $token); $stmt->execute(); $result = $stmt->get_result(); // 检查是否返回了一行数据 if ($result->num_rows === 1) { // 获取邮箱 $row = $result->fetch_assoc(); $email = $row['email']; // 在用户表中标记该邮箱已验证 $update_stmt = $connection->prepare("UPDATE users SET verified = 1 WHERE email = ?"); $update_stmt->bind_param("s", $email); $update_stmt->execute(); // 从验证表中删除该令牌 $delete_stmt = $connection->prepare("DELETE FROM email_verification WHERE token = ?"); $delete_stmt->bind_param("s", $token); $delete_stmt->execute(); // 关闭语句 $stmt->close(); $update_stmt->close(); $delete_stmt->close(); // 重定向到登录页面 header("Location: index.php"); exit; } else { echo "无效令牌或令牌已过期。"; } } else { echo "未提供令牌。"; } // 关闭数据库连接 if (isset($connection)) { $connection->close(); }
令牌编码与传输问题
服务器环境若开启了老旧的magic_quotes_gpc配置,会转义令牌中的特殊字符,导致数据库存储的令牌与URL传递的不一致。可在获取令牌后添加处理:$token = stripslashes($token);。另外,生成验证链接时必须对令牌做URL编码:$verifyLink = "https://你的域名/verify.php?token=" . urlencode($token);,避免特殊字符截断令牌。数据库字符集不一致
本地与服务器数据库的字符集/排序规则不匹配(比如本地用utf8mb4,服务器用latin1),会导致令牌存储时乱码。检查email_verification表的字符集,统一设置为utf8mb4_unicode_ci。缺失令牌过期检查
若email_verification表包含expires_at过期时间字段,但当前代码未做判断,会导致已过期的令牌直接被判定为无效。修改查询语句添加时间校验:$stmt = $connection->prepare("SELECT email FROM email_verification WHERE token = ? AND expires_at > NOW()");数据库连接隐性错误
即使连接信息正确,服务器可能限制了数据库访问IP,或db_connection.php存在隐性错误。在代码开头添加错误输出排查:error_reporting(E_ALL); ini_set('display_errors', 1);令牌重复使用或提前删除
检查验证邮件生成逻辑,是否存在重复插入令牌未覆盖旧记录的情况;用户多次点击链接时,第一次点击后令牌已被删除,后续点击会提示无效。可添加日志记录令牌使用情况,或保留已验证令牌便于排查。
内容的提问来源于stack exchange,提问作者Roland Ruiz

