
本文讲解如何安全地根据数据库中用户的权限字段(如 level4)动态包含 PHP 菜单项,并重点解决因 SQL 字符串拼接缺失引号导致的“Unknown column”致命错误。
本文讲解如何安全地根据数据库中用户的权限字段(如 level4)动态包含 php 菌单项,并重点解决因 sql 字符串拼接缺失引号导致的“unknown column”致命错误。
在构建基于角色的导航系统时,常见需求是:仅当用户具备特定权限(例如 level4 = 'yes')时,才加载管理员专属菜单模块(如 asidemenus/admin.php)。你最初的代码逻辑正确,但存在一个关键的 SQL 注入隐患与语法错误——直接将 $_SESSION['userid'] 拼入查询字符串而未加引号,导致 MySQL 将变量值(如 justinw)误解析为列名而非字符串字面量,从而抛出 Unknown column 'justinw' 的致命错误。
✅ 正确写法(已修复引号问题):
<?php $sql = "SELECT * FROM users WHERE userid = '" . $_SESSION['userid'] . "'";
$result = $con->query($sql);
if ($result && $result->num_rows > 0) {
$row = $result->fetch_assoc();
if ($row["level4"] === 'yes') {
include 'asidemenus/admin.php';
}
}
?>
⚠️ 重要注意事项:
- 不要使用上述拼接方式上线!它仍存在 SQL 注入风险(如 $_SESSION['userid'] 若被篡改为 ' OR '1'='1,将导致全表查询)。
- ✅ 推荐方案:使用预处理语句(Prepared Statements),彻底杜绝注入:
<?php $stmt = $con->prepare("SELECT level4 FROM users WHERE userid = ?"); $stmt->bind_param("s", $_SESSION['userid']); $stmt->execute(); $result = $stmt->get_result();
if ($result && $result->num_rows > 0) { $row = $result->fetch_assoc(); if ($row["level4"] === 'yes') { include 'asidemenus/admin.php'; } } $stmt->close(); ?>
- ? 优化建议:无需 `SELECT *`,仅查询所需字段(如 `level4`),提升性能与安全性; - ? `include` 前建议检查文件是否存在(`file_exists()`),避免因路径错误导致警告; - ? 避免在循环中重复判断——单用户只需一次查询与一次判断,`while` 在此场景冗余,已简化为 `fetch_assoc()` 单次获取。 总结:权限控制的核心在于「安全查询 + 精准判断 + 可维护结构」。优先采用预处理语句,再结合清晰的条件分支,即可稳健实现菜单级权限隔离。










