ASP.NET MVC - Bezpieczne tymczasowe przechowywanie danych kart kredytowych
Mam proces realizacji koszyka na zakupy, który obecnie przechowuje dane karty kredytowej w sesji do pobrania, gdy użytkownik sfinalizuje zakup. Proces zakupu jest skonfigurowany tak, że użytkownik wprowadza kartę kredytową, wyświetla stronę potwierdzenia, a następnie finalizuje zamówienie. Potwierdzenia i działania finalizacyjne to jedyne dwa działania, które wymagają dostępu do danych karty kredytowej i aby być bezpiecznym, wszystkie inne działania powinny ją odrzucić.
Brak refleksji w kontrolerze podstawowym w celu sprawdzenia aktualnej akcji wywoływanej przez użytkownika, nie pozwala mi wymyślić eleganckiego sposobu na odrzucenie danych dotyczących niedozwolonych żądań. Dodatkowo, jeśli użytkownik nie zgłosi kolejnego żądania po wprowadzeniu danych, pozostanie w sesji, dopóki nie powróci na stronę internetową - kiedy to nastąpi. Zaproponowano mi szyfrowanie danych w ukrytym polu i korzystanie z biletu SSL, aby zapobiec buforowaniu znaczników. Wydaje się, że jest to dość bezpieczne podejście, ale nie podoba mi się pomysł zaszyfrowania danych karty kredytowej w dostępnej dla użytkownika lokalizacji. Przechowywanie w bazie danych nie jest możliwe, ponieważ klient nie chce, aby dane karty kredytowej były zapisywane.
Jakie jest idealne podejście do tymczasowego przechowywania poufnych danych, takich jak informacje o karcie kredytowej na więcej niż jednej stronie?
Być może ktoś może mi powiedzieć, czy jest to wystarczające podejście. Ustawiłem mój koszyk, który jest przechowywany w sesji, na unikalny Guid generowany za każdym razem, gdy obiekt jest nowi, a Guid jest używany jako klucz do szyfrowania i deszyfrowania danych karty kredytowej, które serializuję za pomocąAlgorytm Rijndaela. Zaszyfrowane dane karty są następnie przekazywane użytkownikowi w ukrytym polu, a po sfinalizowaniu klikane jest deserializacja. Końcowym wynikiem jest ciąg podobny do tego:
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;
}
}