ユーザーが購入を完了したときに取得できるように、現在クレジット カード データをセッションに保存しているショッピング カートのチェックアウト プロセスがあります。購入プロセスは、ユーザーがクレジット カードを入力し、確認ページを表示して、注文を確定するように設定されています。クレジット カード データへのアクセスが必要なアクションは、確認アクションとファイナライズ アクションの 2 つだけであり、安全を確保するために他のすべてのアクションはデータを破棄する必要があります。
ベースコントローラーでリフレクションを実行して、ユーザーが呼び出している現在のアクションを確認する以外に、許可されていないリクエストのデータを破棄するエレガントな方法を思いつきません。さらに、ユーザーがデータを入力した後に別のリクエストを行わなかった場合、ユーザーがウェブサイトに戻ってくるまでセッションに残ります。私が提供された 1 つの提案は、データを非表示フィールドに暗号化し、SSL チケットに依存してマークアップのキャッシュを防ぐことでした。これはかなり安全なアプローチのように思えますが、クレジット カード データをユーザーがアクセスできる場所に暗号化して配置するかどうかにかかわらず、私はあまり好きではありません。クライアントがクレジット カード データの保存を望まないため、データベースへの保存は無効です。
クレジット カード情報などの機密データを複数のページ リクエストにわたって一時的に永続化するための理想的な方法は何ですか?
これが十分なアプローチであるかどうか、誰かが教えてくれるかもしれません。オブジェクトが新しくなるたびに生成される一意の Guid を持つようにセッションに保存されているショッピング カートを設定しました。その Guid は、Rijndael アルゴリズムでシリアル化しているクレジット カード データを暗号化および復号化するためのキーとして使用されます。暗号化されたカード データは非表示フィールドでユーザーに渡され、[ファイナライズ] をクリックするとデシリアライズされます。最終結果は、次のような文字列になります。
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;
}
}