我有一个购物车的结帐流程,该流程当前正在会话中存储信用卡数据,以便在用户完成购买后进行检索。购买过程设置为用户输入信用卡,查看确认页面,然后完成订单。确认和完成操作是唯一需要访问信用卡数据的两个操作,为了安全起见,所有其他操作都应该丢弃它。
如果没有在基本控制器中进行反射以检查用户正在调用的当前操作,我想不出一种优雅的方式来丢弃不允许的请求中的数据。此外,如果用户在输入数据后未能发出另一个请求,它将在会话中徘徊,直到他们回到网站——无论何时发生。我收到的一个建议是将数据加密到隐藏字段中,并依靠 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;
}
}