防止用户执行两次动作
我们在用户执行两次特定操作时遇到了一些问题,我们有一种机制可以确保用户无法执行操作,但不知何故仍然会发生。这是我们目前的机制是如何工作的:防止用户执行两次动作
- 客户端:按钮将在1次点击被禁用。
- 服务器端:我们在URL中有一个关键的哈希值,它将根据存储在SESSIONS中的关键字进行检查,一旦匹配,关键字被删除。
- 数据库端:执行操作后,会有一个字段被标记,表示用户已完成操作。
但是,通过所有这些措施,仍然有用户能够执行两次操作,还有没有更安全的方法?
这里是数据库端的部分代码:
$db->beginTransaction();
// Get the user's datas
$user = $db->queryRow("SELECT flag FROM users WHERE userid = {$auth->getProperty('auth_user_id)}");
if ($user['flag'] != 0) {
$db->rollback();
// Return with error
return false;
}
// Proceed with performing the action
// --- Action Here ---
// Double checking process, the user data is retrieved again
$user = $db->queryRow("SELECT flag FROM users WHERE userid = {$auth->getProperty('auth_user_id)}");
if ($user['flag'] != 0) {
$db->rollback();
// Return with error
return false;
}
// --- The final inserting query ---
// Update the flag
$db->query("UPDATE users SET flag = 1 WHERE userid = {$auth->getProperty('auth_user_id)}");
$db->commit();
return true;
很高兴地看到,你已经采取了一切措施来打败坏人。在坏人来说的:
客户端:这可以很容易地通过简单的javascript禁用绕过。不管怎样,反正也不会对付坏人。
服务器端:这很重要,但是请确保每次提交都生成不同的散列/密钥。这里是一个good tutorial at nettutes on how to submit forms in a secure fashion.
数据库方面:不知道,但我怀疑,有可能是SQL注入的问题。请参阅有关SQL Injection和how to possibly fix that.
最后的详细信息:
我建议你检查出:
的OWASP PHP项目的目标(OWASP PHP项目路线图)旨在使开发人员,系统管理员和应用程序架构师能够构建和部署使用PHP编程语言构建的安全应用程序。
参数已正确转义,所以我将排除SQL注入。 – TheOnly92 2010-04-17 12:54:49
那么JS方法和Hash方法可能会被一些臭名昭着的人欺骗,但是第三种方法似乎很好,以保护冗余。必须有一些编程缺陷才能通过这个。
为什么不你刚刚检查要插入值,而不是在那里用户执行操作(如果你现在正在做的话)
伪如下页面上的标志字段:
<?
$act_id; // contains id of action to be executed
$h = uniqid('');
// this locks action (if it is unlocked) and marks it as being performed by me.
UPDATE actions SET executor = $h WHERE act_id = $act_id AND executor = '';
SELECT * FROM actions WHERE executor = $h;
//
// If above query resulted in some action execute it here
//
// if you want to allow for executing this exact action in the future mark it as not executed
UPDATE actions SET executor = '' WHERE act_id = $act_id;
重要的事情:
- 首先查询应更新声称 的动作对我来说,如果它是尚未 无人认领。
- 其次应该是查询 抓取动作执行,但只有 如果它是我所声称的。
事实上,最后一个足以阻止第二次执行,所以我猜这个问题不在想法中,而是在实现中。你可以请张贴一些代码吗? – Crozin 2010-04-17 11:28:11
你想看哪一部分代码? – TheOnly92 2010-04-17 11:35:18
我认为最重要的部分是......检查数据库中的*标志并执行操作。 – Crozin 2010-04-17 11:40:22