如何使用PHP防止多次同时提交?

如何使用PHP防止多次同时提交?,php,Php,我这里有一个大问题,我在网上找不到答案 我有一个基本的MVC系统,它有3个组件:模型、视图和控制器 我有一个index.php文件,根据访问者的URI请求包含所有内容 控制器连接视图和模型。我正在页面加载中打开一个文件,并在那里写入一个虚拟文本。问题如下:如果我将sleep1放入控制器,在加载页面之前延迟,访问者可以轻松地多次点击referesh 打开文件并插入多行。我试图在文件写入时创建一个会话,如果它存在,我甚至不运行文件写入 然而,这有一个问题。我已经多次刷新页面进行测试,即使存在会话检查

我这里有一个大问题,我在网上找不到答案

我有一个基本的MVC系统,它有3个组件:模型、视图和控制器

我有一个index.php文件,根据访问者的URI请求包含所有内容


控制器连接视图和模型。我正在页面加载中打开一个文件,并在那里写入一个虚拟文本。问题如下:如果我将sleep1放入控制器,在加载页面之前延迟,访问者可以轻松地多次点击referesh

打开文件并插入多行。我试图在文件写入时创建一个会话,如果它存在,我甚至不运行文件写入

然而,这有一个问题。我已经多次刷新页面进行测试,即使存在会话检查,文件仍然会写入多行代码

所以我猜它会得到一个带有refereshing的简单HTTP请求,所有这些请求都会看到并没有设置会话变量

在页面加载之后,我点击了refresh,它肯定不会插入任何新行,因为会话已经存在。当访问者在一次加载中多次刷新页面时,就会出现此问题

有没有避免这种情况的建议?

锁 如果您在共享资源的多用户环境中工作,则应使用锁定系统。bacis程序是:

尝试锁定资源。如果资源上已经有锁,则无法获取它。如果没有,那就是你的了。 使用资源。 放开锁。这也称为“解锁”或“释放”。 锁的主要优点是它们直接在资源上工作,并且不像会话那样依赖于访问者浏览器中的cookie

您可以用许多不同的方式创建锁。某些资源(如文件)本身支持锁定:

但其他人则不然。您可以创建自己的锁定系统,例如使用数据库表


锁的问题是,有时未发出解锁命令。你需要创造一种方法来处理这个问题。例如,您可以决定锁在一段时间后过期。这是最基本的保护类型。有很多更高级的方法来处理这个问题。

问题是您需要知道会话是如何工作的。会话ID保存到cookie中,并在页面末尾发送到客户端。如果您不等待PHP完成执行,那么每次页面刷新都会有新的会话id。。 我要做的是,它应该适用于99%的情况,即使对于不支持cookie的用户,大多数机器人程序都使用用户IP,有可能两个不同的用户使用相同的IP,但约1%

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
   $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}
将$ip存储为数据库中的uniq userid,并且可能有另一个字段时间戳,以便您可以在XX秒后终止用户id。
这有一些缺陷,但在许多情况下都会起作用。

如果我在控制器中设置sleep1,在加载页面之前延迟,访问者可以轻松地多次点击referesh。-所以不要把sleep1放在代码中。@Gordon我把sleep1放在代码中是有原因的。这是因为将有另一个功能代替该代码,这是一个电子邮件发送,发送大约需要1秒。在这段时间内,访问者可以刷新页面、多次发送电子邮件和多次写入文件。@Gordon如果页面由于大量代码而无法立即加载,并且他们有机会刷新页面,会发生什么情况?我们有同样的问题,不是吗?是的。但那可能是你设计的一个问题。刷新不应改变服务器状态。浏览器通常会在用户通过POST重新提交表单时告知用户。因此,如果用户确认了这一点,他们实际上会重新提交,所以可以写两次。另一方面,刷新(例如GET请求)不应写入某些内容,因为它应该是幂等且安全的。在任何情况下,这就是你想要的吗?我没有投反对票——这是另一个人,但这不是我真正需要的。好吧,你可能是对的。但是你永远不能完全阻止多次提交,你必须处理它。锁是此解决方案的一部分。除了锁定之外,您还必须知道在多次提交相同数据时要做什么。替换旧数据?忽略新输入?