电商网站PHP Session无法正常工作的技术求助
问题描述
我正在搭建一个电商网站项目,初期就遇到了持续的问题:session_start()似乎无法正常工作或无法显示会话内容。我尝试了多种解决方法,最后甚至照搬了YouTube上PacketCode的教程代码,但浏览器仍无预期结果。我原本期望登录后能正常显示会话相关内容,但参考大量代码后问题仍未解决,完全无从下手。
相关代码文件
index.php
<?php session_start(); include "db.php"; include "retrieve.php"; include "function.php"; include "logic.php"; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Exquisite</title> </head> <body> <div class="container" id="main_cntr"> <div id="intro_cntr"> <div id="title_cntr"> <h2>Welcome to </h1> <h1>Exquisite</h1> </div> <div id="paragraph_cntr"> <p>Here to provide an excellent support for your style!</p> </div> </div> <?php if(empty($_SESSION['username'])){?> <div class="container" id="form"> <div id="login_cntr"> <form method="POST"> <h2>Login</h2> <label for="username">Username</label><br> <input type="text" name="username" placeholder="Enter your Username"><br> <label for="password">Password</label><br> <input type="password" name="pass" placeholder="Enter your Password"><br> <input type="submit" name="login" value="Login"> </form> </div> <?php }?> <div id="signupOption_cntr"> <a href="signup(user).php">Create an Account</a> <h4>or</h4> <a href="login(admin).php">Login as Admin</a> </div> </div> <?php if(!empty($_SESSION['username'])){?> <div class="container"> <h1>Hello again<?php echo $_SESSION['username'];?></h1> <form method="POST"> <button name="logout">Logout</button> </form> </div> <?php }?> </div> </body> </html>
db.php
<?php $conn = mysqli_connect('localhost', 'root', '', 'exquisite') or die ("Cannot connect to the Database"); ?>
retrieve.php
<?php if(isset($_REQUEST['login'])){ $uname = $_REQUEST['username']; $pword = $_REQUEST['pass']; } ?>
function.php
<?php function login($conn, $uname, $pword){ $sql = "SELECT * FROM `user_acc` WHERE `username` = '$uname'"; $query = mysqli_query($conn, $sql); return $query; } ?>
logic.php
<?php if(isset($_REQUEST['login'])){ $result = login($conn, $uname, $pword); foreach($result as $r){ $passw_check = password_verify($pword, $r['password']); if($passw_check){ $_SESSION['username'] = $r['username']; header("location: home.php"); } } } if(isset($_REQUEST['logout'])){ session_destroy(); header("location: index.php"); exit(); } ?>
问题根源与修复方案
1. 变量作用域问题
retrieve.php中定义的$uname和$pword仅在自身的if(isset($_REQUEST['login']))代码块内有效,logic.php的同名代码块无法访问这些变量,会直接触发未定义变量错误,导致登录逻辑完全无法执行。
修复:直接在logic.php中获取表单数据,删除retrieve.php(或调整其逻辑):
// logic.php 修正后 if(isset($_POST['login'])){ // 直接从POST获取变量,同时做基础过滤 $uname = trim($_POST['username']); $pword = trim($_POST['pass']); $result = login($conn, $uname, $pword); // ... 后续逻辑 }
2. SQL注入风险
function.php中的SQL语句直接拼接用户输入,存在严重的SQL注入漏洞,同时也可能因输入含特殊字符导致查询失败。
修复:使用MySQLi预处理语句重构login函数:
// function.php 修正后 function login($conn, $uname){ // 仅查询需要的字段,避免返回不必要数据 $sql = "SELECT username, password FROM `user_acc` WHERE `username` = ?"; $stmt = mysqli_prepare($conn, $sql); mysqli_stmt_bind_param($stmt, "s", $uname); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); return $result; }
3. 跳转后未终止脚本执行
登录成功后调用header("location: home.php")但未加exit(),后续代码仍可能执行,导致会话设置被意外覆盖或干扰。
修复:跳转后立即终止脚本:
if($passw_check){ $_SESSION['username'] = $r['username']; header("location: home.php"); exit(); // 必须添加,终止后续代码执行 }
4. 目标页面未启动会话
跳转的home.php如果没有调用session_start(),将无法读取已设置的会话变量,导致页面无法识别登录状态。
修复:在home.php顶部添加:
<?php session_start(); // 检查会话是否有效,若未登录则跳转回登录页 if(empty($_SESSION['username'])){ header("location: index.php"); exit(); } ?>
5. 会话输出缓冲问题
如果session_start()之前有任何输出(包括空格、HTML标签),会导致会话无法正常启动。检查所有PHP文件的开头,确保<?php标签前没有空白字符,且没有提前输出内容。
最终修正后的logic.php完整代码
<?php if(isset($_POST['login'])){ $uname = trim($_POST['username']); $pword = trim($_POST['pass']); $result = login($conn, $uname); // 使用mysqli_fetch_assoc而非foreach遍历结果 $user = mysqli_fetch_assoc($result); if($user && password_verify($pword, $user['password'])){ $_SESSION['username'] = $user['username']; header("location: home.php"); exit(); } else { // 可添加登录失败提示 $_SESSION['error'] = "用户名或密码错误"; } } if(isset($_REQUEST['logout'])){ session_destroy(); // 销毁会话后建议清除会话Cookie if(isset($_COOKIE[session_name()])){ setcookie(session_name(), '', time()-3600, '/'); } header("location: index.php"); exit(); } ?>
内容的提问来源于stack exchange,提问作者IT-boi

