如何防止篡改URL中GET传递的ID以非法读取其他用户数据库数据?
防止URL ID篡改读取他人数据的解决方案
核心思路:绑定数据归属 + 双重校验
不管用哪种方法,核心都是确保只有数据的所有者才能访问对应的数据,以下是具体可落地的方案:
1. Session结合用户身份校验(最稳妥的基础方案)
如果你的系统有用户登录体系,直接通过Session关联用户与数据:
- 第一步:给存储表单数据的数据库表新增
user_id字段,关联用户表的主键(用户注册/登录后,Session中会存储$_SESSION['user_id'])。 - 第二步:用户提交表单并验证通过后,插入数据时同步写入当前用户的
user_id:
// 示例用PDO操作数据库 $stmt = $pdo->prepare("INSERT INTO form_data (content, user_id) VALUES (?, ?)"); $stmt->execute([$validatedContent, $_SESSION['user_id']]); $insertedId = $pdo->lastInsertId();
- 第三步:汇总页查询时,除了URL传递的
id,必须加上user_id的过滤条件,同时用预处理语句防范SQL注入:
$targetId = $_GET['id']; $stmt = $pdo->prepare("SELECT * FROM form_data WHERE id = ? AND user_id = ?"); $stmt->execute([$targetId, $_SESSION['user_id']]); $data = $stmt->fetch(); // 若查询无结果,说明用户无权访问,直接跳转或提示 if (!$data) { echo "<script>alert('无权访问该数据'); window.location.href='index.php';</script>"; exit; }
这样就算有人篡改URL里的id,数据库也只会返回当前用户自己的数据,无法读取他人内容。
2. 加密URL中的ID(额外防护层)
如果担心明文ID暴露数据量或被枚举,可将ID加密后再放到URL中,服务器端解密后再查询:
- 提交后重定向时加密ID:
$plainId = $insertedId; $secretKey = "你的服务器专属密钥(需保密,不能存前端)"; $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc')); $encryptedId = openssl_encrypt($plainId, 'aes-256-cbc', $secretKey, 0, $iv); // 将加密后的ID和IV一同传给前端(IV可公开) $redirectUrl = "summary.php?id=" . urlencode($encryptedId) . "&iv=" . urlencode(base64_encode($iv)); echo "<script>window.location.href='$redirectUrl';</script>";
- 汇总页解密并查询:
$secretKey = "与加密时一致的密钥"; $encryptedId = urldecode($_GET['id']); $iv = base64_decode(urldecode($_GET['iv'])); $plainId = openssl_decrypt($encryptedId, 'aes-256-cbc', $secretKey, 0, $iv); // 依然要结合user_id校验,实现双重保险 $stmt = $pdo->prepare("SELECT * FROM form_data WHERE id = ? AND user_id = ?"); $stmt->execute([$plainId, $_SESSION['user_id']]); $data = $stmt->fetch();
3. 用随机Token替代ID(无用户体系时的方案)
如果项目没有用户登录功能(比如匿名提交场景),可以用随机生成的Token标识数据:
- 提交表单时生成并存储Token:
// 生成16位随机Token $token = bin2hex(random_bytes(16)); $stmt = $pdo->prepare("INSERT INTO form_data (content, token) VALUES (?, ?)"); $stmt->execute([$validatedContent, $token]);
- 重定向到带Token的汇总页:
echo "<script>window.location.href='summary.php?token=$token';</script>";
- 汇总页通过Token查询:
$token = $_GET['token']; $stmt = $pdo->prepare("SELECT * FROM form_data WHERE token = ?"); $stmt->execute([$token]); $data = $stmt->fetch();
由于Token是随机生成的,他人很难猜到有效Token,从而避免篡改访问。
注意事项
- 无论采用哪种方案,必须使用预处理语句(PDO/mysqli prepare),防范SQL注入是基础安全要求。
- Session需做好安全配置:开启
session.cookie_httponly防止XSS窃取Session,开启session.cookie_secure(若使用HTTPS)。
内容的提问来源于stack exchange,提问作者H3ry
相关产品推荐
相关产品推荐

