ASP.NET Core でのデータ保護に関する非 DI 対応シナリオ
作成者: Rick Anderson
通常、ASP.NET Core のデータ保護システムはサービス コンテナーに追加され、依存関係の挿入 (DI) を介して依存するコンポーネントによって使われます。 ただし、既存のアプリにシステムをインポートする場合などに実行できない、または望ましくない場合があります。
このようなシナリオをサポートするために、Microsoft.AspNetCore.DataProtection.Extensions パッケージには具象型である DataProtectionProvider が用意されています。これを利用すると、DI に頼らずにデータ保護を簡単に使うことができます。 DataProtectionProvider
型には IDataProtectionProvider が実装されています。 DataProtectionProvider
を構築するには、次のコード サンプルのように、プロバイダーの暗号キーが格納される場所を示す DirectoryInfo インスタンスを指定するだけで済みます。
using System;
using System.IO;
using Microsoft.AspNetCore.DataProtection;
public class Program
{
public static void Main(string[] args)
{
// Get the path to %LOCALAPPDATA%\myapp-keys
var destFolder = Path.Combine(
System.Environment.GetEnvironmentVariable("LOCALAPPDATA"),
"myapp-keys");
// Instantiate the data protection system at this folder
var dataProtectionProvider = DataProtectionProvider.Create(
new DirectoryInfo(destFolder));
var protector = dataProtectionProvider.CreateProtector("Program.No-DI");
Console.Write("Enter input: ");
var input = Console.ReadLine();
// Protect the payload
var protectedPayload = protector.Protect(input);
Console.WriteLine($"Protect returned: {protectedPayload}");
// Unprotect the payload
var unprotectedPayload = protector.Unprotect(protectedPayload);
Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
Console.WriteLine();
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
/*
* SAMPLE OUTPUT
*
* Enter input: Hello world!
* Protect returned: CfDJ8FWbAn6...ch3hAPm1NJA
* Unprotect returned: Hello world!
*
* Press any key...
*/
DataProtectionProvider
具象型の既定では、生のキーはファイル システムに永続化される前に暗号化されません。 これは、開発者がネットワーク共有を指しても、データ保護システムによって自動的に適切な at-rest キー暗号化メカニズムを推測できないシナリオをサポートするためです。
さらに、DataProtectionProvider
具象型の既定では、アプリの分離は行われません。 同じキー ディレクトリを使うすべてのアプリは、目的パラメーターが一致する限り、ペイロードを共有できます。
DataProtectionProvider コンストラクターは、システムの動作を調整するために使える省略可能な構成コールバックを受け取ります。 次のサンプルは、SetApplicationName を明示的に呼び出して分離を復元する方法を示しています。 また、このサンプルは、Windows DPAPI を使って永続化キーを自動的に暗号化するようにシステムを構成しています。 ディレクトリが UNC 共有を指している場合は、関連するすべてのマシンに共有証明書を配布し、ProtectKeysWithCertificate を呼び出して証明書ベースの暗号化を使うようにシステムを構成することができます。
using System;
using System.IO;
using Microsoft.AspNetCore.DataProtection;
public class Program
{
public static void Main(string[] args)
{
// Get the path to %LOCALAPPDATA%\myapp-keys
var destFolder = Path.Combine(
System.Environment.GetEnvironmentVariable("LOCALAPPDATA"),
"myapp-keys");
// Instantiate the data protection system at this folder
var dataProtectionProvider = DataProtectionProvider.Create(
new DirectoryInfo(destFolder),
configuration =>
{
configuration.SetApplicationName("my app name");
configuration.ProtectKeysWithDpapi();
});
var protector = dataProtectionProvider.CreateProtector("Program.No-DI");
Console.Write("Enter input: ");
var input = Console.ReadLine();
// Protect the payload
var protectedPayload = protector.Protect(input);
Console.WriteLine($"Protect returned: {protectedPayload}");
// Unprotect the payload
var unprotectedPayload = protector.Unprotect(protectedPayload);
Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
Console.WriteLine();
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
ヒント
DataProtectionProvider
具象型のインスタンスは、作成するために高いコストがかかります。 アプリでこの型のインスタンスを複数保守し、そのすべてに同じキー ストレージ ディレクトリが使われている場合、アプリのパフォーマンスが低下する可能性があります。 DataProtectionProvider
型を使う場合は、この型を一度作成し、できるだけ再利用することをお勧めします。 DataProtectionProvider
型とそこから作成されたすべての IDataProtector インスタンスは、複数の呼び出し元に対してスレッドセーフです。
ASP.NET Core