安全地将信用从一个用户转移到另一个用户

时间:2017-01-10 17:54:52

标签: c# asp.net-mvc entity-framework concurrency

我正在一个网站上工作,我在其中使用Asp.Net MVC和Entity Framework 6.每个用户都有一个信用卡,有时用户可以将信用转移给其他用户。简单的方法是:

public class ApplicationUser : IdentityUser
{
    //....
    public decimal Credit { get; set; }
}

var user1 = await db.Users.FindAsync(id1);
var user2 = await db.Users.FindAsync(id2);
user1.Credit -= amount;
user2.Credit += amount;

await db.SaveChangesAsync();

但是,我认为这很容易受到并发问题的影响。例如,如果两个用户在同一时间转移给用户会怎么样?

由于我们将在网站上使用真钱作为信用,因此解决此问题的最安全和防故障方法是什么?

3 个答案:

答案 0 :(得分:1)

答案 1 :(得分:1)

默认情况下,EntityFramework会将<?php and ?>包装到事务中。所以你的改变要么成功要么一起失败。

你能做什么:

事务包装器

  1. 您可以将代码明确地包装到TransactionScope()

    使用(TransactionScope scope = new TransactionScope())         {             //需要在事务中以原子方式工作的代码         }

  2. 或者

    交易表

    1. 使用更好的数据库设计来存储事务而不是最终状态
    2. 这是银行的做法。每当交易发生时,将账户和信用卡的借记存储到另一个账户。

      • 从Joe
      • 拿-50
      • 将+50放到Jane

      然后,当您查询用户的余额时,您将根据所有事务的总和来聚合最终余额(对于任何支持SQL的DBMS都非常容易)

答案 2 :(得分:0)

建议:

  1. 让您的流程首先从旧帐户中删除资金,然后确认交易已过帐到旧帐户,然后将资金应用到新帐户。

  2. 在每次转移时记录序列号,并确认何时向其帐户发布该交易具有该交易的正确序列号。这只是一个很好的做法,因此您可以记录每次转移。

  3. 将债务过账到源帐户后,确认帐户余额不是负数。如果是,请取消交易。这可以防止对现有余额进行多次借记,然后在每次债务应用于源帐户后(最终增加的安全措施)结果为负数。另外,确保转移的金额是正数。一个简单的黑客骗局是从其他人的帐户转移负数(因此增加了黑客的帐户)。

  4. 如果您不信任您使用的框架,有许多方法可以手动执行此操作,并且应该进行许多检查以降低欺诈风险。

    您可以锁定两个记录,进行转移,然后解锁两个记录。锁定前,确保它们尚未锁定。这样,两个记录都会被锁定,直到事务完成。

    没有什么能取代对交易日志的需求,恕我直言。