gpt4 book ai didi

php - 在 CodeIgniter 中处理并发请求

转载 作者:行者123 更新时间:2023-11-29 01:55:23 25 4
gpt4 key购买 nike

假设我已经使用 CodeIgniter/PHP 和 MySQL 创建了一个网上银行系统,并通过以下方式从我的银行账户中取款:

function withdraw($user_id, $amount) {
$amount = (int)$amount;

// make sure we have enough in the bank account
$balance = $this->db->where('user_id', $user_id)
->get('bank_account')->balance;
if ($balance < $amount) {
return false;
}

// take the money out of the bank
$this->db->where('user_id', $user_id)
->set('balance', 'balance-'.$amount, false)
->update('bank_account');

// put the money in the wallet
$this->db->where('user_id', $user_id)
->set('balance', 'balance+'.$amount, false)
->update('wallet');

return true;
}

首先,我们检查用户是否可以执行取款,然后我们从账户中减去,然后我们添加到钱包。

问题是我几乎可以同时发送多个请求(使用 curl 这基本上是微不足道的)。每个请求都有自己的线程,所有线程都同时运行。因此,每个人都执行检查以查看我的银行中是否有足够的钱(我这样做),然后每个人都执行提款。结果,如果我开始余额为 100,并且我发出两个 curl 请求同时导致这样的 100 提款,那么我的钱包里有 200 和 -100在我的银行帐户中,这是不可能的。

解决此类 TOCTOU 漏洞的正确“CodeIgniter”方法是什么?

最佳答案

我将 bank_accountwallet 表的存储引擎设置为 InnoDB它具有交易支持,然后包含一个 FOR UPDATE SELECT 语句中的子句在交易期间锁定 bank_account 表。

代码将如下所示。

function withdraw($user_id, $amount) {
$amount = (int)$amount;

$this->db->trans_start();

$query = $this->db->query("SELECT * FROM bank_account WHERE user_id = $user_id AND balance >= $amount FOR UPDATE");

if($query->num_rows() === 0) {
$this->db->trans_complete();
return false;
}

$this->db->where('user_id', $user_id)
->set('balance', 'balance-'.$amount, false)
->update('bank_account');

$this->db->where('user_id', $user_id)
->set('balance', 'balance+'.$amount, false)
->update('wallet');

$this->db->trans_complete();

return true;
}

关于php - 在 CodeIgniter 中处理并发请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30608820/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com