$transfer_amount = GetTransferAmount();
$balance = GetBalanceFromDatabase();
if ($transfer_amount < 0) {
FatalError("Bad Transfer Amount");
}
$newbalance = $balance - $transfer_amount;
if (($balance - $transfer_amount) < 0) {
FatalError("Insufficient Funds");
}
SendNewBalanceToDatabase($newbalance);
NotifyUser("Transfer of $transfer_amount succeeded.");
NotifyUser("New balance: $newbalance");
如果有一个安全问题,此代码可能有人解释一下吗?
答案 0 :(得分:6)
财务交易中非常重要的安全机制是执行审计的能力。没有迹象表明该代码会留下任何形式的纸张痕迹。一个人不仅应该更新余额,而且还要创建交易记录。
该代码存在竞争条件。考虑如果两个动作同时发生,会发生什么。
Process 1 Process 2
=============================================== ===============================================
$xfer_amt = GetTransferAmount();
$balance = GetBalanceFromDatabase();
if ($xfer_amt < 0) {
FatalError("Bad Transfer Amount");
}
$xfer_amt = GetTransferAmount();
$balance = GetBalanceFromDatabase();
if ($xfer_amt < 0) {
FatalError("Bad Transfer Amount");
}
$newbalance = $balance - $xfer_amt;
if (($balance - $xfer_amt) < 0) {
FatalError("Insufficient Funds");
}
$newbalance = $balance - $xfer_amt;
if (($balance - $xfer_amt) < 0) {
FatalError("Insufficient Funds");
}
SendNewBalanceToDatabase($newbalance);
NotifyUser("Transfer of $xfer_amt succeeded.");
NotifyUser("New balance: $newbalance");
SendNewBalanceToDatabase($newbalance);
NotifyUser("Transfer of $xfer_amt succeeded.");
NotifyUser("New balance: $newbalance");
(重命名了一个变量,使代码在屏幕上更合适。)
数据库只会最终被其中一项交易扣除。
在合并第一个问题的解决方案时,正确执行此操作会变得更加复杂,因为您需要确保余额始终与事务记录保持同步(考虑并发事务,网络故障,断电,等)。
资金从何而来?在大多数情况下,使用提取的资金做某事可能会失败。如果是这样,您可能不应该提取资金,而应该保留它们(标记为不可用),并且只有在实际使用它们之后才提取它们。