表格POST或会话?

时间:2011-01-07 19:50:04

标签: php forms

如果您有一个允许用户添加评论的项目,您如何传递用户正在回复的项目?

我虽然在表单中使用了隐藏字段,但是可以使用诸如firebug之类的插件轻松更改:

<form method="post" action="blah">
<input type="hidden" name="item_id" value="<?php echo $item_id; ?>">
<!-- other form data here -->
<input type="submit" name="submit">
</form>

或者只是简单地使用会话:

$_SESSION['item_id'] = $item_id

是否有安全的方式以表格形式发送项目数据?

修改 这是验证后的,...我确实实现了一些XSS保护(表单令牌等)。我问的原因只是要知道最佳做法是什么。

我做了类似

的事情
$_SESSION['item_id'] = $id //this is set when they visit the current item

然后在表单中有一个隐藏字段:

<input type="hidden" name="item_id" value="<?php echo $id?>">

最后检查会话是否与点击的id匹配:

if ($_SESSION('item_id') !== $item_id) //the value posted in the form
{
   die('There\'s got to be a morning after
       If we can hold on through the night
       We have a chance to find the sunshine
       Let\'s keep on looking for the light');
}

然而,在阅读了一些评论后,我想这是一个坏主意?

公平地说(@Surreal Dreams):如果他们确实改变了身份证,这并不是什么大不了的事情,正如我所说,我只是在寻找最好的做法。

干杯。

6 个答案:

答案 0 :(得分:8)

以您建议的方式使用会话会搞乱(1)访问者在多个标签中打开多个不同文章的情况,以及(2)尝试在除最后打开的标签之外的任何标签上写回复。用户甚至可以在不同的选项卡中同时写两个回复;我有时会在StackOverflow上这样做。 Web开发人员很容易忘记今天的访问者可能同时打开多个浏览器选项卡。真的,我们不再使用IE6了。

解决方案是让$_SESSION['item_id']成为最近查看的文章ID的数组,但是您将无法阻止某些Firebug用户(或任何其他技术娴熟的人)回复以前查看过的文章。添加时间限制也不会改变任何内容。

但是为什么有人会故意更改他们回复的帖子的ID,除了对网站进行欺骗或垃圾邮件?如果有人真的想要搞砸你的网站,他们可以通过在发布垃圾评论之前让他们的机器人请求适当的页面来轻松绕过任何保护。投资更好的CSRF令牌生成器,垃圾邮件过滤器,速率限制器等,你会好得多。

答案 1 :(得分:1)

老实说,你可能还可以使用隐藏的表单元素。如果您真的担心有人会更改它,您可以随时base64()对其进行编码,以使其更改。

但是,您始终可以在页面上设置会话变量,然后在提交表单时调用该值。

表格

<?
session_start();

//Make a random ID for this form instance
$form_id = rand(1, 500);

//Set session variable for this form
$_SESSION[$form_id]['item_id'] = $item_id;
?>

<form method="post" action="process.php?n=<?=$form_id?>">
<!-- form data here -->
<input type="submit" name="submit">
</form>

<强>过程

<?
session_start();

//Process only if the number submitted matches the SESSION variable
if(array_key_exists($_GET['n'], $_SESSION) {
  //Process tasks
  echo $_SESSION[$_GET['n']['item_id'];

  //Unset session variable when done processing
  unset($_SESSION[$_GET['n']);
}
?>

答案 2 :(得分:1)

使用隐藏字段。

如果用户修改DOM以表明它是对不同评论的回复,那么呢?它只影响他们。

如果要限制用户可以回复的内容,则需要实施适当的访问控制层,而不是尝试在用户界面中强制执行。

答案 3 :(得分:1)

正如你可能已经注意到愤怒的,挥舞着干草叉的暴徒,由于多个标签之类的问题,这两种解决方案都不是很令人满意。

如果真的担心人们能够在他们最初访问的另一个对象上发表评论,请考虑使用数组将它们存储在$ _SESSION中,并让他们使用隐藏的表单发回ID。如果回发的值不在数组中,那么它显然是一个他没有看的帖子。

为了提高防篡改性,考虑散列ID(当然是慷慨的盐渍),并将其存储在阵列中。

请注意,我觉得你可能正试图在这里解决错误的问题;为什么不验证该人是否有权对他评论的帖子发表评论?如果您有访问权限,那么您应该被允许发表评论 - 如果您想要篡改ID并使您的评论最终落在错误的帖子之外......那么,这基本上就是您的问题。我的意思是,用户也可以转到另一个帖子,并在那里手动做出错误的评论......那么问题是什么?

答案 4 :(得分:1)

你可以有这样的表格

<?
$saltedhash = md5("MYSEED"+$item_id;)
?>

<form method="post" action="blah">
<!-- form data here -->
<input type="hidden" name="item_id" value="<? echo $item_id ?>">
<input type="hidden" name="item_hash" value="<? echo $saltedhash ?>">
<input type="submit" name="submit">
</form>

这样,您可以随时检查传递的item_id是否与其对应的哈希匹配,并查看用户是否更改了它。

然而,正如其他人指出的那样,这不会阻止用户在不同的项目上发布,就好像他们可以从某个地方获取哈希值...访问控制机制会更好

答案 5 :(得分:-1)

使用$ _SESSION存储帖子ID是理想的解决方案,因为它确实无法修改该值。

话虽如此,有人这样做有什么好处?同样,许多评论系统都有一个批准过程,要求管理员在发布之前批准评论。

但是,我建议坚持使用会话值。