2010-04-17 95 views
2

我们在用户执行两次特定操作时遇到了一些问题,我们有一种机制可以确保用户无法执行操作,但不知何故仍然会发生。这是我们目前的机制是如何工作的:防止用户执行两次动作

  1. 客户端:按钮将在1次点击被禁用。
  2. 服务器端:我们在URL中有一个关键的哈希值,它将根据存储在SESSIONS中的关键字进行检查,一旦匹配,关键字被删除。
  3. 数据库端:执行操作后,会有一个字段被标记,表示用户已完成操作。

但是,通过所有这些措施,仍然有用户能够执行两次操作,还有没有更安全的方法?

这里是数据库端的部分代码:

$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; 
+2

事实上,最后一个足以阻止第二次执行,所以我猜这个问题不在想法中,而是在实现中。你可以请张贴一些代码吗? – Crozin 2010-04-17 11:28:11

+0

你想看哪一部分代码? – TheOnly92 2010-04-17 11:35:18

+0

我认为最重要的部分是......检查数据库中的*标志并执行操作。 – Crozin 2010-04-17 11:40:22

回答

1

很高兴地看到,你已经采取了一切措施来打败坏人。在坏人来说的:

最后的详细信息:

我建议你检查出:

OWASP PHP Project

的OWASP PHP项目的目标(OWASP PHP项目路线图)旨在使开发人员,系统管理员和应用程序架构师能够构建和部署使用PHP编程语言构建的安全应用程序。

+0

参数已正确转义,所以我将排除SQL注入。 – TheOnly92 2010-04-17 12:54:49

0

那么JS方法和Hash方法可能会被一些臭名昭着的人欺骗,但是第三种方法似乎很好,以保护冗余。必须有一些编程缺陷才能通过这个。

为什么不你刚刚检查要插入值,而不是在那里用户执行操作(如果你现在正在做的话)

+0

这是在双方完成... – TheOnly92 2010-04-17 13:02:27

+0

好吧,我看到了你的代码。你在$ db-> queryRow()中获取查询吗? 。你可以通过打印$ user ['flag']来测试它也可以使用(0!= $ user ['flag']),并且我没有看到任何重复查询检查的点 – nik 2010-04-17 13:23:18

+0

我有理论可能查询处理很慢,并且在设置标志之前执行重复的请求,所以我认为重复检查可能会更好。国旗已正确设置,我已经彻底测试过了。 – TheOnly92 2010-04-17 13:30:20

0

伪如下页面上的标志字段:

<? 

$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; 

重要的事情:

  • 首先查询应更新声称 的动作对我来说,如果它是尚未 无人认领。
  • 其次应该是查询 抓取动作执行,但只有 如果它是我所声称的。