ASP.NET MVC - 信用卡数据的安全临时存储

时间:2009-12-22 16:51:30

标签: asp.net-mvc session cookies rijndaelmanaged hidden-field

我有一个购物车的结帐流程,当前用户最终确定购买时,会在会话中存储信用卡数据以供检索。设置购买过程,使得用户输入信用卡,查看确认页面,然后完成订单。确认和终止操作是需要访问信用卡数据的唯一两个操作,并且为了安全,所有其他操作都应该丢弃它。

如果没有在基本控制器中进行反射来检查用户正在调用的当前操作,我想不出一种优雅的方法来丢弃不允许的请求上的数据。此外,如果用户在输入数据后未能提出另一个请求,它将在会话中停留,直到他们回到网站 - 每当发生这种情况时。我提出的一个建议是将数据加密到隐藏字段并依赖SSL票证来防止缓存标记。这似乎是一种相当安全的方法,但我不太喜欢将信用卡数据放在用户可访问的位置加密或不加密的想法。存储在数据库中是因为客户端不希望保存信用卡数据。

在多个页面请求中临时保存信用卡信息等敏感数据的理想方法是什么?


也许有人可以告诉我这是否是一个充分的方法。我已经设置了存储在会话中的购物车,每次创建对象时都会生成一个唯一的Guid,并且Guid用作加密和解密我使用{{3}序列化的信用卡数据的密钥}。然后,加密的卡数据在隐藏字段中传递给用户,并在单击完成后反序列化。最终结果是一个非常类似的字符串:

VREZ%2bWRPsfxhNuOMVUBnWpE%2f0AaX4hPgppO4hHpCvvwt%2fMQu0hxqA%2fCJO%2faOEi%2bX3n9%2fP923mVestb7r8%2bjkSVZDVccd2AJzCr6ak7bbZg8%3d

public static string EncryptQueryString(object queryString, Guid encryptionKey)
{
    try
    {
        byte[] key = Encoding.UTF8.GetBytes(ShortGuid.Encode(encryptionKey).Truncate(16));//must be 16 chars
        var rijndael = new RijndaelManaged
                           {
                               BlockSize = 128,
                               IV = key,
                               KeySize = 128,
                               Key = key
                           };

        ICryptoTransform transform = rijndael.CreateEncryptor();

        using (var ms = new MemoryStream())
        {
            using (var cs = new CryptoStream(ms, transform, CryptoStreamMode.Write))
            {
                byte[] buffer = Encoding.UTF8.GetBytes(queryString.ToString());

                cs.Write(buffer, 0, buffer.Length);
                cs.FlushFinalBlock();
                cs.Close();
            }
            ms.Close();
            return HttpUtility.UrlEncode(Convert.ToBase64String(ms.ToArray()));
        }
    }
    catch
    {
        return null;
    }
}

3 个答案:

答案 0 :(得分:11)

处理此方案的最佳方法是使用支持两件事的付款服务:

  1. 授权 - >完成语义。
  2. 标记化
  3. 授权允许您在收到付款信息时保留指定的费用金额,然后完成后,您可以在确认付款/订单后将付款提交到付款批次。如果订单被取消,您不必签发“完成”,也可以尝试删除授权。

    关于标记化,支持上述处理付款方法的大多数网关将为挂起的事务返回令牌,通常是数字ID。然后可以根据需要处理令牌,因为它对没有访问网关的身份验证凭据的任何人都没有价值。这也将安全负担转移到网关。

    以除了将费用转发到网关/处理器之外的任何方式存储实际的信用卡信息是一个坏主意。除了保护数据的问题之外,这还将使您的应用程序进入PCI / PABP的卡信息存储范围,这需要您在应用程序中不需要处理的许多规则和规定。我相信,对于合规申请,明年还将收取监管费,据称是1万美元。所有这些对您或您的客户来说可能都不值得。

    最后,在中间处理(页内/事件/路由处理程序)期间,您可以使用SecureString保存数据的内容,直到您不再需要它们为止。

    SecureString class (System.Security) @ MSDN

答案 1 :(得分:2)

使用TempData怎么样?您需要在确认和终止操作之间将值重新放回TempData,但至少每次请求都会丢弃它。请注意,TempData使用Session进行存储,因此在存储时不会更安全,但它确实具有自动删除功能。我也会拒绝在页面上存储该号码。我怀疑这违反了PCI规则。

另一种选择是将卡信息存储在数据库中。如果您在应用程序中完全保留它,那么您可能已经受到PCI规则的约束。将其存储在数据库中会使其变得更加容易,因此您只需将计费卡ID放入后续请求中即可。这可能很容易陷入隐藏的领域。

答案 2 :(得分:0)

这个基于哪个国家/地区以及涉及哪些信用卡公司?实际上将完整的信用卡号码发送回客户端(无论采用何种形式)的整个方法使得这听起来像是您没有处理专业信用卡处理(请不要将其视为侮辱)。

您的客户是否愿意违反Visa / MasterCard / AMC / Discover的在线信用卡处理(PCI DSS)的集体规则?您的客户可能会被主要信用卡公司禁止与他们进行交易。一般来说,尝试滚动自己的在线信用卡处理解决方案是一个非常糟糕的主意 - 它比滚动自己的加密算法更糟糕,因为可能会对您的客户进行严重罚款(商家协议中的细则)。真正的PCI DSS解决方案需要数万美元的认证和审核,以确保以真正安全的方式处理信用卡数据 - 这就是为什么几乎每个人都使用现有的在线处理器。