php 你如何确保 $_POST 数据来自你的表单而不是外部影响?
Posted
技术标签:
【中文标题】php 你如何确保 $_POST 数据来自你的表单而不是外部影响?【英文标题】:php How do you ensure $_POST data is coming from your form and not a outside influence? 【发布时间】:2012-05-18 15:03:39 【问题描述】:有没有办法确保我的代码收到的$_POST
数据来自我的表单,而不是外部影响。基本上我不希望有人能够将$_POST
欺骗到一个普遍可用的页面,例如帐户创建。任何用户都可以访问帐户创建页面,但我想确保只有我的 account_creation 表单提交的数据才会得到处理。
我唯一能想到的就是启动$_SESSION
,然后使用隐藏输入将 session_id 提供给表单。在 $_POST 之后,隐藏输入的值将与当前 session_id 匹配。
如果有更好的方法来达到这个结果?如果有我期待听到它。
【问题讨论】:
【参考方案1】:您无法确保数据来自表单。 POST 请求只是一个 POST 请求,它可以通过多种方式生成。 html 表单只是一种非常用户友好的方式。您的服务器需要验证通过 POST 请求接收到的数据是否有效以及是否对其进行操作。
话虽如此,有些东西可以帮助您限制和验证正在提交的数据。首先,要求用户使用(会话)cookies 登录。这消除了匿名用户的随机请求。其次,您可以将令牌作为隐藏字段嵌入到您也保存到用户会话中的表单中。 POST 请求需要包含该令牌才能有效。令牌只是一个伪随机字符串。 您可以通过准备您希望用户提交的表单字段的哈希来增强这一点。如果表单值应该是只读的,您也可以将该值包含到散列中。例如:
$rand = md5(mt_rand());
$hash = sha1('lastname:firstname:email:' . $rand);
$_SESSION['rand'] = $rand;
$_SESSION['hash'] = $hash;
// on form submit:
$keys = array_keys($_POST);
$checkHash = sha1(join(':', $keys) . ':' . $_SESSION['rand']);
if ($checkHash != $_SESSION['hash'])
die('Form submission failed token validation');
这只是一个简单的示例,您可能希望按字母顺序对键进行排序,以确保获得相同的哈希值等。它演示了用户需要为每个请求拥有唯一令牌的概念,但这会阻止修改表单并提交比预期更多或更少的数据。
但这并不意味着用户实际上使用了您的表单来提交数据。
【讨论】:
【参考方案2】:$ref = $_SERVER['HTTP_REFERER'];
if($ref !== 'some site path/index.php')
die("Access Denied!");
这应该可以防止大多数人将数据发布到您的数据库中,以免受到外部影响。
【讨论】:
我很惊讶你没有被“可以被欺骗”的悲观主义者淹没【参考方案3】:稍微好一点的是添加额外的验证,例如 user_agent、user_ip 和其他一些 $_SERVER 变量——我使用的就是这两个。
因此,按照您的描述创建唯一 ID(或会话 ID),但添加一些额外的验证,即代理和 ip 也匹配。不是万无一失,但增加了另一层安全性。
编辑:我应该补充一点,您不会将用户代理发回;保留该服务器端并根据返回的会话 ID 静默验证。
此外,如果提交未通过验证,切勿向用户透露原因 - 这样作弊者就不会知道您是如何跟踪他们的。您还可以添加“5 个无效者,您出局”跟踪,但您需要为此登录。
【讨论】:
【参考方案4】:使用会话 ID 无疑是一种方法。但是还有其他选项,其中大部分(如果不是全部)涉及添加一些数据作为隐藏字段。
-
使用验证码。这对于每个页面加载始终是唯一的,因此必须使用您的表单。
生成随机数据并将其存储在数据库中(或只是
$_SESSION
变量)并在提交表单后检查它。
选项一是我推荐的用户创建表单,因为它具有双重职责。它会停止自动提交您自己的表单,同时确保 $_POST
数据来自您自己的表单。
【讨论】:
【参考方案5】:这是防止 XSRF 的标准模式模式。本质上它与您提到的类似。当为用户呈现表单时,服务器会创建一个随机令牌。它与用户的浏览器 cookie 相关联。在表单提交时,它会被发送回服务器。然后服务器将令牌与发出的令牌进行比较,只有在成功匹配后才会执行表单操作。
【讨论】:
【参考方案6】:在表单中放置一个唯一值并与服务器端会话中存储的值相匹配,有很多很好的提及。这样做,但也要考虑当用户使用后退按钮并可能尝试提交表单两次,或者他们打开第二个浏览器窗口(同一个会话!),或者他们在您的网站上使用多个表单时会发生什么。
不要因为没有仔细考虑您的系统而造成疯狂的错误。
【讨论】:
感谢您的帮助,我没有想到此操作可能产生的其他影响。虽然我认为这些问题可以使用if(!isset($_SESSION['hash']))create hashelseuse existing hash
之类的东西来避免。以上是关于php 你如何确保 $_POST 数据来自你的表单而不是外部影响?的主要内容,如果未能解决你的问题,请参考以下文章
PHP 使用 new FormData() 和 append() 处理来自 XMLHttpRequest2 的 $_POST