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

Php 一种在表单中存储表ID的有效方法,使用户无法覆盖另一个表记录,php,security,encryption,spoofing,Php,Security,Encryption,Spoofing,我正在创建一个有用户帐户的网站。对于每个用户帐户,用户都可以更新个人信息、写博客等。 当用户想要编辑博客时,我有以下表单(这是一个简化版本) 现在你可以看到这个用户的blogID是4,所以当他们更新记录时,它会用ID 4更新blog表。现在使用firebug或其他欺骗技术,用户可以将此ID更改为8,并更新记录8,这可能是其他人的条目 我如何防止这种情况? 到目前为止,我已经想到了两种方法,想知道你认为什么是最好的主意(或者建议另一种) 使用随机字符串对ID进行编码,然后在提交后对字符串进行解

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


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

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

  • 使用随机字符串对ID进行编码,然后在提交后对字符串进行解码,检索正确的ID
  • 将其保留为数字,然后进行检查以确保更新后,通过数据库查询其记录 显然,我想限制数据库查询,通过编码ID,我认为是更好的选择。你们觉得怎么样


    提前感谢

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

    在构建web应用程序时,如果您假设以下情况,您将最高兴:

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

  • 应用程序是无状态的。您不能仅仅因为希望请求X前面加上请求Y就认为它们是这样发生的


  • 你的选择2是更好的选择。如果您要求经过身份验证的用户更新博客文章,并且您要求该用户获得更新博客文章的授权,那么请在更新博客文章的代码中检查这些要求。对于太多的db查询,您可能不会遇到问题,如果遇到了问题,您可以在遇到问题时处理它。

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

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

  • 在会话变量中存储用户有权访问的所有博客,提交时检查提交的博客是否在会话数组中,如果不是拒绝

  • 因为您说过要限制db查询,所以可以将另一个where条件附加到更新查询中。实际的查询当然取决于您的db模式

    更新博客集。。。剪其中BLOG id=FORM\u SUBMITTED\u id和BLOG.owner=CURRENT\u USER

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


  • 内德·巴奇尔德的回答中有一些非常重要的事情需要记住,我不再重复了

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

    假设:

    • blog表有一个名为ownerId的列,该列保存拥有/创建帖子的用户的用户ID
    • 您有某种用户登录系统,并且在会话的某个地方存储了一个用户ID
    确保用户只更新自己的帖子的最简单方法是事先检查:

    <?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不应该允许这样做的时候?你是什么意思?基本上是:选择二。只有您应该在更新之前检查其条目是否正确。
    
    <?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);