一种在表单中存储表ID的有效方法,因此用户无法覆盖另一个表记录

时间:2010-06-27 22:18:30

标签: php security encryption spoofing

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

<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的博客表。现在使用firebug或其他欺骗技术,用户可以将此ID更改为某些内容像8,更新记录8,这可能是别人的条目。

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

  1. 使用随机字符串对ID进行编码,然后在提交后解码字符串,检索正确的ID。
  2. 将其作为数字编号,然后通过数据库查询检查以确保更新后的记录。
  3. 我显然想限制数据库查询,并通过编码ID我相信是更好的选择。你们有什么感想?

    提前致谢

4 个答案:

答案 0 :(得分:2)

构建Web应用程序时,如果您采取以下措施,您将会感到最开心:

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

  2. 该应用程序是无状态的。您不能认为仅仅是因为您打算请求X在请求Y之前,它们就是这样发生的。

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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

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

  3. 由于您说要限制数据库查询,因此您可以在更新查询中添加另一个where条件。实际查询当然取决于您的数据库模式。

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

    这将确保仅在用户是实际所有者时才进行更新。

答案 3 :(得分: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条件将匹配零记录。