PHP登录重定向异常求助:URL重复拼接错误
问题根源
错误的核心原因是使用basename()函数处理HTTP来源URL,而basename()是为文件系统路径设计的,并非URL解析工具。当$_SERVER['HTTP_REFERER']为网站根域名(如https://www.website.com)时,basename()会返回www.website.com而非预期的页面路径,拼接后就会生成../www.website.com?error=xxx的错误重定向地址,最终被解析为重复域名的URL。
解决方案
替换所有依赖basename()解析URL的逻辑,改用PHP的parse_url()函数安全提取来源页面的路径部分,同时增加异常 fallback 逻辑避免referer不存在的情况。
步骤1:添加URL路径解析辅助函数
在functions.inc.php中新增一个工具函数,用于安全获取来源页面的相对路径:
function getSafeRefererPath() { // 默认跳转主登录页面,可根据你的两个登录入口调整 $defaultPath = 'login.php'; if (!isset($_SERVER['HTTP_REFERER'])) { return $defaultPath; } $urlParts = parse_url($_SERVER['HTTP_REFERER']); $path = isset($urlParts['path']) ? $urlParts['path'] : '/'; // 如果来源是根目录,返回默认登录页面 if ($path === '/' || empty($path)) { return $defaultPath; } // 去掉路径开头的斜杠,转为相对路径 return ltrim($path, '/'); }
步骤2:修改登录函数中的重定向逻辑
更新loginUser函数里的错误重定向部分:
function loginUser ($username, $password, $conn){ $uidExists = uidExists($conn, $username, $username); if ($uidExists === false) { $result = false; $refererPath = getSafeRefererPath(); // 拼接错误参数 $errorUrl = strpos($refererPath, '?') !== false ? $refererPath . "&error=wrongLogin" : $refererPath . "?error=wrongLogin"; header("location: ../".$errorUrl); exit(); } $pwdHashed = $uidExists ['password']; $password= $_POST['pwd']; $checkPwd = password_verify($password, $pwdHashed); if ($checkPwd === false) { $refererPath = getSafeRefererPath(); $errorUrl = strpos($refererPath, '?') !== false ? $refererPath . "&error=wrongLogin" : $refererPath . "?error=wrongLogin"; header("location: ../".$errorUrl); exit(); }else if ($checkPwd === true) { session_start(); $_SESSION["userid"] = $uidExists ["id"]; $_SESSION["useruid"] = $uidExists ["username"]; $_SESSION["role"] = $uidExists["role"]; $userID = $uidExists ["id"]; if ($uidExists['resetFlag']!=0) { header("location: ../profile.php?resetFlag=1"); }else{ header("location: ../dashboard.php"); } $result = true; } return $result; }
步骤3:修改Login.inc.php中的重定向逻辑
更新Login.inc.php里的空输入错误处理部分:
<?php session_start(); if (isset($_POST["submit"])) { $username = $_POST['uid']; $password = $_POST['pwd']; require_once 'functions.inc.php'; require_once 'dbh.inc.php'; if (isset($_POST['data'])){ if (emptyInputLogin($username, $password) !== false) { $refererPath = getSafeRefererPath(); $errorUrl = strpos($refererPath, '?') !== false ? $refererPath . "&error=emptyinput" : $refererPath . "?error=emptyinput"; header("location: ../".$errorUrl); exit(); } $data = $_SESSION['idata']; $locoData = $_SESSION['locoData']; uploadLogin($conn, $username, $password, $data, $locoData); }else{ if (emptyInputLogin($username, $password) !== false) { $refererPath = getSafeRefererPath(); $errorUrl = strpos($refererPath, '?') !== false ? $refererPath . "&error=emptyinput" : $refererPath . "?error=emptyinput"; header("location: ../".$errorUrl); exit(); } loginUser($username, $password, $conn); } }else{ header("location: ../login.php"); }
额外注意事项
$_SERVER['HTTP_REFERER']并非100%可靠(浏览器可能不发送或被篡改),所以设置默认跳转路径很重要。- 如果你的两个登录入口有明确的文件名(如
login.php和admin-login.php),可以在辅助函数中根据referer的路径判断,返回对应的登录页面,确保跳转回原登录入口。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

