1

我正在创建一个具有用户帐户的网站。对于每个用户帐户,用户可以执行更新个人详细信息、写博客等操作。当用户想要编辑博客时,我有以下表格(这是一个简化版本)。

<form action="goToThisPage.php" method="get">
    <input type="hidden" name="blogID" value="4" />
    <input type="text" name="blogTitle" value="" />
    <textarea name="blogContent"></textarea>
    <input type="submit" name="submit" value="Update Blog" />
</form>

现在你可以看到这个用户的 blogID 是 4,所以当他们更新记录时,它会用 ID 4 更新博客表。现在使用萤火虫或其他欺骗技术,用户可以将此 ID 更改为 8,并更新记录 8,这可能是其他人的条目。

我该如何防止这种情况?到目前为止,我已经想到了两种方法,想知道你认为什么是最好的想法(或建议另一个)。

  1. 使用随机字符串对 ID 进行编码,然后在提交后解码字符串,检索正确的 ID。
  2. 将其保留为数字,然后检查以确保一旦更新,其记录将通过数据库查询。

我显然想限制数据库查询,并且通过对 ID 进行编码,我认为是更好的选择。你们有什么感想?

提前致谢

4

4 回答 4

2

在构建 Web 应用程序时,如果您假设以下内容,您将是最快乐的:

  1. 客户端(即浏览器)不可信。假设发送到您的服务器的任何数据都是由坏人发送的。

  2. 该应用程序是无状态的。您不能仅仅因为您打算将请求 X 放在请求 Y 之前就假设它们是以这种方式发生的。

您的选项 2 是更好的选择。如果您需要经过身份验证的用户来更新博客文章,并且您需要授权用户这样做,请在更新博客文章的代码中检查这些要求。您可能不会遇到太多数据库查询的问题,如果您这样做,您可以在这样做时处理它。

于 2010-06-27T22:24:12.297 回答
0

Ned Batchelder 的回答包含一些非常重要的东西要记住,我不会重复它们。

我将概述一些更多的实现细节。

假设:

  • 博客表有一个名为 ownerId 的列,其中包含拥有/创建帖子的任何用户的 userId。
  • 您有某种用户登录系统,并且在会话中存储了一个 userId。

确保用户只更新自己的帖子的最简单方法是事先检查:

<?PHP
$blog = get_blog_by_id($_POST['blogId']);
if ($blog['ownerId'] != $_SESSION['userId']){
   die("You're a BAD MAN.  Cut it out!");
}
$blog['blogContent'] = $_POST['blogContent'];
$blog['blogTitle'] = $_POST['blogTitle'];

update_blog($blog); //escapes any strings, and runs an update.

如果您真的不想在更新之前从数据库中提取博客文章,无论出于何种原因,您总是可以执行以下操作:

<?PHP
$title = mysql_real_escape_string($_POST['blogTitle']);
$content = mysql_real_escape_string($_POST['blogContent']);
$id = mysql_real_escape_string($_POST['blogId']);
$userId = $_SESSION['userId'];

$sql = "UPDATE blog SET blogTitle='$title', blogContent='$content' WHERE blogId = '$id' AND ownerId = $user_id";

mysql_query($sql);

这为您节省了初始查找,但如果当前用户不拥有博客,则基本上会静默失败,因为 WHERE 条件将匹配零记录。

于 2010-06-27T23:31:27.377 回答
0

在 HTML 级别上做任何事情都是浪费时间。PHP 根本不应该允许这样做,也就是检查条目是否实际上属于发出更改的用户。

于 2010-06-27T22:20:24.313 回答
0

有很多方法可以解决这个问题,其中一些是:

  1. 散列(sha1 或类似)一个秘密字符串以及 id,在提交时验证散列。如果不匹配,则拒绝。

  2. 将用户可以访问的所有博客存储在会话变量中,提交时检查提交的博客是否在会话数组中,如果不是则拒绝。

  3. 既然您说您想限制数据库查询,您可以将另一个 where 条件附加到您的更新查询。实际查询当然取决于您的数据库模式。

    UPDATE blogs SET ... snip ... WHERE BLOG id = FORM_SUBMITTED_ID AND blog.owner = CURRENT_USER

    这将确保仅当用户是实际所有者时才发生更新。

于 2010-06-27T22:59:23.143 回答