8

有没有办法确保$_POST我的代码收到的数据来自我的表单而不是外部影响。基本上我不希望有人能够欺骗$_POST一个普遍可用的页面,例如创建帐户。任何用户都可以访问帐户创建页面,但我想确保只有我的 account_creation 表单提交的数据才能得到处理。

我唯一能想到的是启动一个$_SESSION,然后使用隐藏输入将 session_id 提供给表单。在 $_POST 之后,隐藏输入的值将与当前 session_id 匹配。

如果有更好的方法来达到这个结果?如果有我期待听到它。

4

6 回答 6

8

您无法确保数据来自表单。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');
}

这只是一个简单的示例,您可能希望按字母顺序对键进行排序,以确保获得相同的哈希值等。它演示了用户需要为每个请求拥有一个唯一令牌的概念,尽管这可以防止对表单进行调整并提交比想要的更多或更少的数据。

但这并不意味着用户实际上使用了您的表单来提交数据。

于 2012-05-10T04:00:49.110 回答
3
$ref = $_SERVER['HTTP_REFERER'];
if($ref !== 'some site path/index.php')
{
    die("Access Denied!");
}

这应该可以防止大多数人将数据发布到您的数据库中,以免受到外部影响。

于 2014-12-27T07:00:17.677 回答
1

稍微好一点的方法是添加额外的验证,例如 user_agent、user_ip 和其他一些 $_SERVER 变量——这就是我使用的两个。

因此,按照您的描述创建唯一 ID(或会话 ID),但添加一些额外的验证,代理和 ip 也匹配。不是万无一失的,但增加了另一层安全性。

编辑:我应该补充一点,您不会将用户代理发回;保留该服务器端并针对返回的会话 ID 进行静默验证。

此外,如果提交未通过验证,切勿向用户透露原因 - 这样作弊者不知道您如何跟踪他们。您还可以添加“5 无效并且您出局”跟踪,但您需要为此进行某种登录。

于 2012-05-10T03:59:22.753 回答
1

使用会话 ID 无疑是一种方法。但是还有其他选项,其中大多数(如果不是全部)涉及将一些数据添加为隐藏字段。

  1. 使用验证码。这对于每个页面加载始终是唯一的,因此必须强制使用您的表单。
  2. 生成随机数据并将其存储在数据库(或只是$_SESSION变量)中,并在提交表单后检查它。

选项一是我推荐的用户创建表单,因为它具有双重职责。它会停止自动提交您自己的表单,同时确保$_POST数据来自您自己的表单。

于 2012-05-10T03:59:38.447 回答
0

这是防止 XSRF 的标准模式模式。本质上它与您提到的类似。当为用户呈现表单时,服务器会创建一个随机令牌。它与用户的浏览器 cookie 相关联。在表单提交时,它会被发送回服务器。然后服务器将令牌与发出的令牌进行比较,并且只有在成功匹配后才会执行表单操作。

于 2012-05-10T04:04:08.467 回答
0

有很多关于在表单中放置唯一值并与服务器端会话中存储的值匹配的好消息。这样做,但也要考虑当用户使用后退按钮并可能尝试提交表单两次,或者他们打开第二个浏览器窗口(同一个会话!),或者他们在您的网站上使用多个表单时会发生什么。

不要通过不考虑您的系统来创建疯狂的错误。

于 2012-05-10T04:43:22.130 回答