ASP.NET MVC - 信用卡数据的安全临时存储 [英] ASP.NET MVC - Secure Temporary Storage of Credit Card Data

查看:274
本文介绍了ASP.NET MVC - 信用卡数据的安全临时存储的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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






也许有人可以告诉我这是否是一个充分的方法。我已经设置我的购物车存储在会话中具有唯一的Guid生成每次对象被更新,并且该Guid用作加密和解密信用卡数据的密钥,我使用 Rijndael algorithm 。加密的卡数据然后在隐藏字段中被传递给用户,并且在完成被点击之后被反序列化。最终结果是这样的字符串:

  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)); //必须是16个字符
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;
}
}


解决方案

处理此情况的最佳方式是使用支持以下两种操作的付款服务:


  1. 授权 - >完成语义
  2. b $ b
  3. 令牌化

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



关于标记化,大多数网关支持上述处理支付的方法将为待处理的交易返回令牌,通常是数字ID。然后可以根据需要处理令牌,因为它对没有访问网关处的认证证书的任何人没有价值。



以任何方式存储实际信用卡信息,而不是将费用转发到网关/处理器是一个坏主意。除了保护数据的问题之外,这还会将您的应用程序纳入PCI / PABP的卡信息存储范围,这需要许多您不想在应用程序中处理的规则和法规。我相信在未来一年会有合规申请的监管费用,据称是10万美元。



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



SecureString类(System.Security)@ MSDN


I have a checkout process for a shopping cart that is currently storing credit card data in the session for retrieval once the user finalizes the purchase. The purchase process is set up such that the user inputs the credit card, views a confirmation page, and then finalizes the order. The confirmation and finalization actions are the only two actions that need access to the credit card data and to be safe all other actions should discard it.

Short of doing reflection in a base controller to check the current action the user is calling, I cannot think of an elegant way to discard the data on the disallowed requests. Additionally, if the user fails to make another request after entering the data it will linger in the session until they come back to the website- whenever that happens. One suggestion I was offered was encrypting the data into a hidden field and relying on the SSL ticket to prevent caching the markup. This seems like a fairly safe approach, but I don't much like the idea of placing the credit card data in a user-accessible location encrypted or not. Storing in the database is out because the client does not want credit card data saved.

What is the ideal approach to temporarily persisting sensitive data like credit card information across more than one page request?


Perhaps someone can tell me if this is a sufficient approach. I have set my Shopping Cart which is stored in the session to have a unique Guid generated every time the object is newed and that Guid is used as a key to encrypt and decrypt the credit card data which i am serializing with the Rijndael algorithm. The encrypted card data is then passed to the user in a hidden field and deserialized after finalize is clicked. The end result is a string much like this:

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

解决方案

The best way to handle this scenario is to use a payment service that supports two things:

  1. Authorization -> Completion semantics.
  2. Tokenization

Authorization allows you to reserve the designated charge amount at the time the payment information is received, and then Completion allows you to commit the charge to the payment batch once the payment/order is confirmed. If the order is canceled, you don't have to issue a Completion and you can also attempt to delete the authorization as well.

Regarding tokenization, most gateways that support the aforementioned method of handling payments will return a token, typically a numeric id, for the pending transaction. The token may then be handled however you wish, as it has no value to anyone without access to your authentication credentials at the gateway. This transfers the burden of safety to the gateway as well.

Storing the actual credit card information in any way other than relaying a charge to a gateway/processor is a bad idea. Beyond the problems of securing the data, this will also put your application into card information storage scope for PCI/PABP, which entails a lot of rules and regulations that you won't want to deal with in your application. I believe there is also a regulatory fee that will be imposed in the coming year for compliant applications, reputedly $10k USD. All of this is likely not worth the trouble to you or your client.

Last, during intermediate processing (in-page/event/route handlers), you can use a SecureString to hold the contents of the data until you no longer need them.

SecureString class (System.Security) @ MSDN

这篇关于ASP.NET MVC - 信用卡数据的安全临时存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆