9

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

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

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


也许有人可以告诉我这是否足够。我已将存储在会话中的购物车设置为在每次更新对象时生成一个唯一的 Guid,并且该 Guid 用作加密和解密我正在使用Rijndael 算法序列化的信用卡数据的密钥。然后将加密的卡数据在隐藏字段中传递给用户,并在单击 finalize 后反序列化。最终结果是一个非常像这样的字符串:

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;
    }
}
4

3 回答 3

11

处理这种情况的最佳方法是使用支持两件事的支付服务:

  1. 授权 -> 完成语义。
  2. 代币化

授权允许您在收到付款信息时保留指定的费用金额,然后完成允许您在确认付款/订单后将费用提交到付款批次。如果订单被取消,您不必发出完成,您也可以尝试删除授权。

关于标记化,大多数支持上述处理支付方法的网关将为待处理的交易返回一个标记,通常是一个数字 id。然后可以按照您的意愿处理该令牌,因为它对任何无法在网关访问您的身份验证凭据的人没有任何价值。这也将安全负担转移到网关。

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

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

SecureString 类 (System.Security) @ MSDN

于 2009-12-22T17:15:47.643 回答
2

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

另一种选择是将卡信息存储在数据库中。如果您将它完全保留在您的应用程序中,那么您可能已经受制于 PCI 规则。将其存储在数据库中会更容易,因为您只需将账单卡 ID 放入后续请求中。这很容易在一个隐藏的领域。

于 2009-12-22T17:06:49.600 回答
0

它位于哪个国家/地区,涉及哪些信用卡公司?将完整的信用卡号码实际发送回客户(以任何形式)的整个方法听起来就像您没有处理过专业的信用卡处理(请不要认为这是一种侮辱)。

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

于 2009-12-22T17:16:28.437 回答