本文介绍在Web应用中使用GET方法传递ID进行数据库查询时,如何有效防止用户篡改URL中的ID以非法访问他人数据,重点讲解基于会话(Session)的身份校验与权限控制方案。
本文介绍在Web应用中使用GET方法传递ID进行数据库查询时,如何有效防止用户篡改URL中的URL中的ID以非法访问他人数据,重点讲解基于会话(Session)的身份校验与权限控制方案。
在实际开发中,许多初学者会采用类似 summary.php?id=123 的方式,通过GET参数直接查询数据库记录。这种方式虽简洁,却存在严重的越权访问(Insecure Direct Object Reference, IDOR)风险:用户只需修改URL中的id值(如改为id=124),即可尝试读取其他用户的敏感数据——这在教育项目或真实系统中均属高危漏洞。
正确做法不是隐藏或混淆ID(如改用UUID或哈希),而是强制实施访问控制:每次请求必须验证“当前登录用户是否有权查看该ID对应的数据”。
在插入数据成功并重定向前,将新生成的记录ID与当前用户标识(如$_SESSION['user_id'])一同存入服务端Session:
// process_form.php(表单处理页)if ($insert_success) {$_SESSION['last_submission_id'] = $new_record_id; // 仅存储本次操作ID$_SESSION['user_id'] = $current_user_id; // 确保已登录且有用户身份header('Location: summary.php');exit;}
不再信任 $_GET['id'],而是从Session中取出ID,并双重校验:
user_id字段是否等于当前登录用户ID。// summary.phpsession_start();// 1. 强制登录检查if (!isset($_SESSION['user_id'])) {die('Access denied: Not logged in.');}$allowed_id = $_SESSION['last_submission_id'] ?? null;if (!$allowed_id) {die('Access denied: No valid submission found.');}// 2. 数据库查询:必须关联用户身份$stmt = $pdo->prepare("SELECT * FROM submissions WHERE id = ? AND user_id = ?");$stmt->execute([$allowed_id, $_SESSION['user_id']]);$record = $stmt->fetch();if (!$record) {die('Access denied: Record not found or unauthorized.');}// 安全输出数据echo "<h2>Your Submission</h2>";echo "<p>Name: " . htmlspecialchars($record['name']) . "</p>";// ... 其他字段
$_GET['id']、$_COOKIE、甚至前端隐藏字段均可被篡改,唯一可信的是服务端Session + 数据库级归属校验。session_start()、设置合理超时(ini_set('session.gc_maxlifetime', 1800))、使用HTTPS传输Cookie(session_set_cookie_params(['secure' => true, 'httponly' => true]))。WHERE user_id = ?条件,而非依赖前端传入ID。总结:安全的本质不在于让ID“难猜”,而在于确保每次请求都经过身份认证 + 数据归属授权双重校验。将业务逻辑与权限控制深度耦合,才是防御越权访问的坚实基础。