Ich habe einen Checkout-Prozess für einen Einkaufswagen, der derzeit Kreditkartendaten in der Sitzung zum Abruf speichert, sobald der Benutzer den Kauf abgeschlossen hat. Der Kaufvorgang ist so eingerichtet, dass der Benutzer die Kreditkarte eingibt, eine Bestätigungsseite ansieht und dann die Bestellung abschließt. Die Bestätigungs- und Finalisierungsaktionen sind die einzigen beiden Aktionen, die Zugriff auf die Kreditkartendaten benötigen, und um sicher zu sein, sollten alle anderen Aktionen sie verwerfen.ASP.NET MVC - Sichere temporäre Speicherung von Kreditkartendaten
Kurz vor der Reflektion in einem Basis-Controller, um die aktuelle Aktion zu überprüfen, die der Benutzer aufruft, kann ich mir keine elegante Möglichkeit vorstellen, die Daten über die unzulässigen Anfragen zu verwerfen. Wenn der Benutzer nach dem Eingeben der Daten keine weitere Anfrage macht, bleibt er in der Sitzung, bis er auf die Website zurückkehrt - wann immer dies geschieht. Ein Vorschlag, der mir unterbreitet wurde, bestand darin, die Daten in ein verstecktes Feld zu verschlüsseln und sich auf das SSL-Ticket zu verlassen, um das Zwischenspeichern des Markups zu verhindern. Dies scheint ein ziemlich sicherer Ansatz zu sein, aber mir gefällt die Idee nicht, die Kreditkartendaten an einem für den Benutzer zugänglichen Ort verschlüsselt oder nicht zu speichern. Das Speichern in der Datenbank ist nicht möglich, da der Client keine Kreditkartendaten speichern möchte.
Was ist der ideale Ansatz, um vertrauliche Daten wie Kreditkarteninformationen über mehr als eine Seitenanforderung vorübergehend zu erhalten?
Vielleicht kann mir jemand sagen, ob das ein ausreichender Ansatz ist. Ich habe meinen Einkaufswagen festgelegt, der in der Sitzung gespeichert wird, um jedes Mal, wenn das Objekt neu erstellt wird, ein eindeutiges Guid zu generieren, und Guid wird als ein Schlüssel zu dem Verschlüsseln und dem Entschlüsseln der Kreditkartendaten verwandt, die ich mit dem Rijndael algorithm serialisiert. Die verschlüsselten Kartendaten werden dann an den Benutzer in einem versteckten Feld übergeben und deserialisiert, nachdem auf finalisieren geklickt wurde. Das Endergebnis ist eine Zeichenfolge viel wie folgt aus:
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;
}
}
In Bezug auf Ihr Update: Die Verschlüsselung der Karteninformationen ist nicht die Hürde - es ist schwierig sicherzustellen, dass alle Teile der Lösung sicher sind. Wo speichern Sie beispielsweise die GUID, die als Schlüssel verwendet wird? Hat noch jemand Zugriff auf den Server, der die GUIDs generiert? (Dies kann es jemandem ermöglichen, die GUIDs zu erraten). Verwenden Sie dieselbe GUID pro Sitzung oder pro Anwendungslebensdauer? – meklarian
Auch der Fang {} Block ist ein wenig beängstigend. Wäre es nicht besser, dort einfach eine leere Schnur zurückzugeben? – meklarian
Guter Punkt auf dem ToString() Meklarian. Ich habe das von irgendwo anders kopiert, ohne zu genau hinzusehen. Die GUID wird einmal pro Benutzer pro Sitzung generiert, daher wäre es sehr schwierig, die Guid eines Benutzers zu erhalten, denke ich. –