確認要求
セキュリティ確認要求呼び出しを宣言的または強制的に使用することで、直接または間接の呼び出し元が、作成したライブラリにアクセスするために持っている必要があるアクセス許可を指定できます。 直接の呼び出し元は、ライブラリの静的メソッドまたはインスタンス メソッドを明示的に呼び出しますが、間接の呼び出し元は、そのライブラリを呼び出す別のライブラリの静的メソッドまたはインスタンス メソッドを呼び出します。 確認要求を使用すると、作成したコードを含んだアプリケーションは、コードの直接および間接のすべての呼び出し元がその確認要求で指定されたアクセス許可を持っている場合にだけ実行されます。 確認要求は、作成したクラス ライブラリが、信頼されていないコードからのアクセスを避ける必要がある、保護されたリソースを使用している場合には特に有用です。 確認要求は、強制構文または宣言構文のいずれかを使用してコード内に配置できます。
.NET Framework のほとんどのクラスには既に確認要求が関連付けられているため、保護されているリソースにアクセスするクラスを使用するときに、追加の確認要求を作成する必要はありません。 たとえば、StreamWriter クラスを開くと、FileIOPermission を要求するセキュリティ確認要求が自動的に生成されます。 そのため、StreamWriter クラスを使用するときに FileIOPermission に対する確認要求をわざわざ作成すると、重複した非効率なスタック ウォークが行われることになります。 カスタム アクセス許可を必要とするカスタム リソースを保護するには、確認要求を使用する必要があります。
確認要求は、宣言的または強制的に実行できます。
スタック ウォーク
確認要求は、スタック ウォークという分析を実行することによってセキュリティを適用します。この分析では、現在の呼び出し履歴のすべての呼び出し関数 (またはスタック フレーム) が指定されたアクセス許可に対してチェックされます。確認要求がトリガーされると、次の処理が行われます。
スタック ウォークは、確認要求が発生している現在のスタックではなく、呼び出し元のスタック フレームで開始されます。たとえば、メソッド A がメソッド B を呼び出し、メソッド B に確認要求が発生している場合、スタック ウォークはメソッド A のスタック フレームから開始されます。このスタック ウォークでは、メソッド B は評価されません。
スタック ウォークは、スタックのプログラム エントリ ポイント (通常は Main メソッド) に到達するか、またはアサートなどのスタック ウォーク修飾子が見つかるまで呼び出し履歴を処理します。スタック ウォーク修飾子については、「セキュリティ チェックのオーバーライド」を参照してください。
同じアクセス許可に対する確認要求とスタック ウォーク修飾子 (アサートなど) が同じスタック フレームにある場合は、確認要求が優先されます。
宣言的および強制的な構文における動作の違いはありません。
スタック ウォークは常に呼び出し元のスタック フレームから開始されるため、プログラム エントリ ポイントに置かれた確認要求は評価されません。ただし、この場合は評価する呼び出し元のフレームはありません。したがって、プログラム エントリ ポイントに置かれた確認要求は常に成功します。
宣言的な確認要求
宣言的な確認要求は、属性を使用してコードのメタデータに情報を配置します。 宣言構文を使用すると、確認要求をコードのクラス レベルまたはメソッド レベルに配置できます。
宣言セキュリティ チェックをクラス レベルに配置すると、そのセキュリティ チェックはクラスの各メンバーに適用されます。 ただし、宣言セキュリティ チェックをメンバー レベルに配置すると、セキュリティ チェックはそのメンバーだけに適用され、クラス レベルでアクセス許可が指定されていても、そのアクセス許可はオーバーライドされます。 たとえば、クラス レベルではアクセス許可 A が必要であると指定し、そのクラスのメソッド 1 にはアクセス許可 B が必要であると指定したとします。 メソッド 1 が呼び出された場合、セキュリティ チェックはアクセス許可 B についてだけ行われますが、このクラスの他のメソッドでは、依然としてアクセス許可 A が必要です。
ReadData メソッドのすべての呼び出し元に CustomPermission というカスタム アクセス許可を要求する宣言的な確認要求を配置する例を次に示します。 このアクセス許可は架空のカスタム許可であり、.NET Framework には実在しません。 このカスタム アクセス許可には別個に定義された CustomPermissionAttribute があり、この属性が確認要求を実行します。 次の例では、実行する確認要求の種類を指定するために、この属性に SecurityAction.Demand フラグが指定されています。
<CustomPermissionAttribute(SecurityAction.Demand, Unrestricted := True)>Public Shared Function ReadData() As String
'Read from a custom resource.
End Function
[CustomPermissionAttribute(SecurityAction.Demand, Unrestricted = true)]
public static string ReadData()
{
//Read from a custom resource.
}
強制的な確認要求
強制的な確認要求をメソッド レベルに配置するには、アクセス許可オブジェクトの新しいインスタンスを作成し、そのオブジェクトの Demand メソッドを呼び出します。 強制構文を使用して確認要求をクラス レベルに配置することはできません。
強制的な確認要求をコード内に配置すると、Demand メソッドを呼び出すメソッド内のその他すべてのコードも効率的に保護できるようになります。 Demand メソッドが実行されるとセキュリティ チェックが実行されます。セキュリティ チェックが失敗すると SecurityException がスローされ、そのメソッドまたはメンバー内の残りのコードは、その SecurityException がキャッチされて処理されない限りは実行されません。
強制構文を使用して、すべての呼び出し元について、カスタム アクセス許可 CustomPermission に対する確認要求を配置する例を次に示します。 このコードは、コンストラクターに PermissionState.Unrestricted フラグを渡し、CustomPermission クラスの新しいインスタンスを作成します。 その後に Demand メソッドが呼び出されます。
Public Shared Sub ReadData()
Dim MyPermission As New CustomPermission(PermissionState.Unrestricted)
MyPermission.Demand()
'Read from a custom resource.
End Sub
public static void ReadData()
{
CustomPermission MyPermission = new CustomPermission(PermissionState.Unrestricted);
MyPermission.Demand();
//Read from a custom resource.
}
注意
確認要求の最適の動作は、64 ビットと 32 ビットのプラットフォームで異なります。64 ビットのプラットフォームでは、他の呼び出し元アセンブリがない場合、確認要求が含まれるアセンブリの許可セットはチェックされません。ただし、呼び出し元アセンブリがある場合はスタック ウォークが実行されるため、この最適化によって特権の昇格は起こりません。32 ビットのプラットフォームでは、確認要求およびすべての呼び出し元アセンブリを含むアセンブリの許可セットがチェックされます。