Assert メソッドの使用Using the Assert Method

注意事項

コードアクセスセキュリティ (CAS) と部分信頼コードCode Access Security (CAS) and Partially Trusted Code

.NET Framework には、コード アクセス セキュリティ (CAS) と呼ばれる、同一アプリケーションで実行される各種コードにさまざまな信頼レベルを強制的に適用するメカニズムが備わっています。The .NET Framework provides a mechanism for the enforcement of varying levels of trust on different code running in the same application called Code Access Security (CAS).

CAS は、.NET Core、.NET 5、またはそれ以降のバージョンではサポートされていません。CAS は、7.0 より後のバージョンの C# ではサポートされていません。CAS is not supported in .NET Core, .NET 5, or later versions. CAS is not supported by versions of C# later than 7.0.

.NET Framework の CA は、コードの作成やその他の id の側面に基づいてセキュリティ境界を適用するためのメカニズムとして使用しないでください。CAS in .NET Framework should not be used as a mechanism for enforcing security boundaries based on code origination or other identity aspects. CA と Security-Transparent コードは、部分的に信頼されたコード、特に不明な配信元のコードを含むセキュリティ境界としてはサポートされません。CAS and Security-Transparent Code are not supported as a security boundary with partially trusted code, especially code of unknown origin. 発生元の不明なコードの読み込みと実行に関しては、他のセキュリティ対策を適切に導入することなく行わないようにしてください。We advise against loading and executing code of unknown origins without putting alternative security measures in place. .NET Framework は、CA サンドボックスに対して検出される可能性がある昇格した特権の悪用に対して、セキュリティ更新プログラムを発行しません。.NET Framework will not issue security patches for any elevation-of-privilege exploits that might be discovered against the CAS sandbox.

このポリシーは .NET Framework のすべてのバージョンに適用されますが、Silverlight に含まれる .NET Framework には適用されません。This policy applies to all versions of .NET Framework, but does not apply to the .NET Framework included in Silverlight.

Assert は、コードのアクセス許可のクラスおよび PermissionSetクラスで呼び出すことができるメソッドです。Assert is a method that can be called on code access permission classes and on the PermissionSet class. Assertを使用すると、コード (および下流の呼び出し元) が、コードが実行するアクセス許可を持っているものの、その呼び出し元が実行するアクセス許可を持っていないアクションを実行できるようになります。You can use Assert to enable your code (and downstream callers) to perform actions that your code has permission to do but its callers might not have permission to do. セキュリティ アサーションは、セキュリティ チェック時にランタイムが実行する正常なプロセスを変更します。A security assertion changes the normal process that the runtime performs during a security check. アクセス許可をアサートすると、アサートされたアクセス許可のためにコードの呼び出し元をチェックしないようセキュリティ システムに指示します。When you assert a permission, it tells the security system not to check the callers of your code for the asserted permission.

注意事項

アサーションはセキュリティ ホールを開き、セキュリティの制限事項を適用するランタイムのメカニズムを弱体化させる可能性があるため、慎重に使用してください。Use assertions carefully because they can open security holes and undermine the runtime's mechanism for enforcing security restrictions.

アサーションは、ライブラリがアンマネージ コードを呼び出す状況、またはライブラリの使用目的と明らかに関係のないアクセス許可を必要とする呼び出しを行う状況に役立ちます。Assertions are useful in situations in which a library calls into unmanaged code or makes a call that requires a permission that is not obviously related to the library's intended use. たとえば、アンマネージコードを呼び出すすべてのマネージコードは、 UnmanagedCodeフラグが指定されたSecurityPermissionを持つ必要があります。For example, all managed code that calls into unmanaged code must have SecurityPermission with the UnmanagedCode flag specified. ローカルのイントラネットからダウンロードするコードなど、ローカル コンピューターから発生していないコードには、既定でこのアクセス許可は付与されません。Code that does not originate from the local computer, such as code that is downloaded from the local intranet, will not be granted this permission by default. そのため、ローカルのイントラネットからダウンロードするコードがアンマネージ コードを使用するライブラリを呼び出せるようにするには、ライブラリによってアサートされたアクセス許可がコードに指定されている必要があります。Therefore, in order for code that is downloaded from the local intranet to be able to call a library that uses unmanaged code, it must have the permission asserted by the library. さらに、ライブラリによっては呼び出し元からは見えない呼び出し、および特別なアクセス許可を必要とする呼び出しを行う場合があります。Additionally, some libraries might make calls that are unseen to callers and require special permissions.

また、コードが呼び出し元から完全に非表示にされる方法でリソースにアクセスする状況において、アサーションを使用することもできます。You can also use assertions in situations in which your code accesses a resource in a way that is completely hidden from callers. たとえば、ライブラリがデータベースから情報を取得しますが、プロセス内でコンピューターのレジストリからも情報を読み取ると仮定してください。For example, suppose your library acquires information from a database, but in the process also reads information from the computer registry. ライブラリを使用している開発者は、ソースにアクセスできないため、コードを使用するためにコードがRegistryPermissionを必要としていることを知る方法がありません。Because developers using your library do not have access to your source, they have no way of knowing that their code requires RegistryPermission in order to use your code. この場合、コードの呼び出し元がレジストリへのアクセス許可を持つことを求めるのは妥当でないか不必要と判断した場合は、レジストリを読み取るアクセス許可をアサートすることができます。In this case, if you decide that it is not reasonable or necessary to require that callers of your code have permission to access the registry, you can assert permission for reading the registry. このような状況では、 RegistryPermissionのない呼び出し元がライブラリを使用できるように、ライブラリがアクセス許可をアサートするのが適切です。In this situation, it is appropriate for the library to assert the permission so that callers without RegistryPermission can use the library.

アサーションがスタック ウォークに影響を与えるのは、アサートされたアクセス許可および下流の呼び出し元によって要求されるアクセス許可が同じ型である場合、かつ要求されたアクセス許可がアサートされているアクセス許可のサブセットである場合のみです。The assertion affects the stack walk only if the asserted permission and a permission demanded by a downstream caller are of the same type and if the demanded permission is a subset of the asserted permission. たとえば、C:\ をアサートして C ドライブ上のすべてのファイルを読み取る場合、 fileiopermissionが C:\Temp 内のファイルを読み取るために下流の要求が行われると、アサーションはスタックウォークに影響を与える可能性があります。ただし、 FileIOPermissionから C ドライブに書き込む必要がある場合、アサーションは無効になります。For example, if you assert FileIOPermission to read all files on the C drive, and a downstream demand is made for FileIOPermission to read files in C:\Temp, the assertion could affect the stack walk; however, if the demand was for FileIOPermission to write to the C drive, the assertion would have no effect.

アサーションを実行する場合、コードにアサートしているアクセス許可と、アサーションを実行する権利を表す SecurityPermission の両方が付与されている必要があります。To perform assertions, your code must be granted both the permission you are asserting and the SecurityPermission that represents the right to make assertions. コードに付与されていないアクセス許可をアサートすることができますが、アサーションがセキュリティ チェックを成功させようとする前にセキュリティ チェックが失敗するため、アサーションが無意味になってしまいます。Although you could assert a permission that your code has not been granted, the assertion would be pointless because the security check would fail before the assertion could cause it to succeed.

次の図は、 Assertを使用した場合の動作を示しています。The following illustration shows what happens when you use Assert. 次のステートメントについて、アセンブリ A、B、C、E、および F が true であり、P1 と P1A という 2 つのアクセス許可があると仮定してください。Assume that the following statements are true about assemblies A, B, C, E, and F, and two permissions, P1 and P1A:

  • P1A は C ドライブ上の .txt ファイルを読み取る権限を表します。P1A represents the right to read .txt files on the C drive.

  • P1 は C ドライブ上のすべてのファイルを読み取る権限を表します。P1 represents the right to read all files on the C drive.

  • P1A と P1 はどちらもFileIOPermission型であり、P1A は p1 のサブセットです。P1A and P1 are both FileIOPermission types, and P1A is a subset of P1.

  • アセンブリ E と F には P1A のアクセス許可が付与されています。Assemblies E and F have been granted P1A permission.

  • アセンブリ C には P1 のアクセス許可が付与されています。Assembly C has been granted P1 permission.

  • アセンブリ A と B には P1 と P1A のアクセス許可のいずれも付与されていません。Assemblies A and B have been granted neither P1 nor P1A permissions.

  • メソッド A はアセンブリ A 内にあり、メソッド B はアセンブリ B 内にあり、以下同様です。Method A is contained in assembly A, method B is contained in assembly B, and so on.

Assert メソッドアセンブリを示す図。

このシナリオでは、メソッド A が B を呼び出し、B は c を呼び出し、C は E を呼び出し、E は F を呼び出します。メソッド C は、c ドライブ (アクセス許可 P1) 上のファイルを読み取るためのアクセス許可をアサートし、メソッド E は C ドライブ (アクセス許可 P1A) で .txt ファイルを読み取るアクセス許可を要求します。In this scenario, method A calls B, B calls C, C calls E, and E calls F. Method C asserts permission to read files on the C drive (permission P1), and method E demands permission to read .txt files on the C drive (permission P1A). 実行時に F の要求が発生した場合、F で始まるすべての呼び出し元のアクセス許可を確認するためにスタックウォークが実行されます。 P1A のアクセス許可が付与されているため、スタックウォークは C のアクセス許可を調べ、C のアサーションを検出します。When the demand in F is encountered at run time, a stack walk is performed to check the permissions of all callers of F, starting with E. E has been granted P1A permission, so the stack walk proceeds to examine the permissions of C, where C's assertion is discovered. 要求されたアクセス許可 (P1A) は、アサートされたアクセス許可 (P1) のサブセットであるため、スタック ウォークが停止し、セキュリティ チェックは自動的に成功します。Because the demanded permission (P1A) is a subset of the asserted permission (P1), the stack walk stops and the security check automatically succeeds. アセンブリ A と B に P1A のアクセス許可が付与されていないことは関係ありません。It does not matter that assemblies A and B have not been granted permission P1A. P1 をアサートすることで、メソッド C は、呼び出し元がそのリソースへのアクセス許可を付与されていない場合でも呼び出し元が、P1 で保護されているリソースにアクセスできることを保証します。By asserting P1, method C ensures that its callers can access the resource protected by P1, even if the callers have not been granted permission to access that resource.

クラス ライブラリをデザインし、クラスが保護されたリソースにアクセスする場合は、ほとんどの場合、呼び出し元のクラスが適切なアクセス許可を持つことを求めるセキュリティの要求を行う必要があります。If you design a class library and a class accesses a protected resource, you should, in most cases, make a security demand requiring that the callers of the class have the appropriate permission. その後、ほとんどの呼び出し元にアクセス許可がないことがわかっている操作を実行し、呼び出し元がコードを呼び出すことを許可する必要がある場合は、コードが実行している操作を表すアクセス許可オブジェクトでassertメソッドを呼び出すことにより、アクセス許可をアサートできます。If the class then performs an operation for which you know most of its callers will not have permission, and if you are willing to take the responsibility for letting these callers call your code, you can assert the permission by calling the Assert method on a permission object that represents the operation the code is performing. この方法でAssertを使用すると、通常は、コードを呼び出すことができなかった呼び出し元を呼び出すことができます。Using Assert in this way lets callers that normally could not do so call your code. そのため、アクセス許可をアサートする場合、自分のコンポーネントが誤使用されるのを防ぐために、必ず事前に適切なセキュリティ チェックを実行する必要があります。Therefore, if you assert a permission, you should be sure to perform appropriate security checks beforehand to prevent your component from being misused.

たとえば、信頼性の高いライブラリのクラスにファイルを削除するメソッドがあると仮定します。For example, suppose your highly trusted library class has a method that deletes files. メソッドは、アンマネージ Win32 関数を呼び出してファイルにアクセスします。It accesses the file by calling an unmanaged Win32 function. 呼び出し元は、削除するファイルの名前を渡して、コードのDeleteメソッドを呼び出し、C:\Test.txt します。A caller invokes your code's Delete method, passing in the name of the file to be deleted, C:\Test.txt. Deleteメソッド内で、コードは FileIOPermission C:\Test.txt への書き込みアクセスを表すオブジェクトを作成します。Within the Delete method, your code creates a FileIOPermission object representing write access to C:\Test.txt. (ファイルを削除するには書き込みアクセスが必要です)。コードは、 FileIOPermissionオブジェクトのDemandメソッドを呼び出すことによって、強制セキュリティチェックを呼び出します。(Write access is required to delete a file.) Your code then invokes an imperative security check by calling the FileIOPermission object's Demand method. コール スタックのいずれかの呼び出し元にこのアクセス許可がない場合は、SecurityException がスローされます。If one of the callers in the call stack does not have this permission, a SecurityException is thrown. 例外がスローされない場合、すべての呼び出し元に C:\Test.txt へのアクセス権があることがわかります。If no exception is thrown, you know that all callers have the right to access C:\Test.txt. ほとんどの呼び出し元にはアンマネージコードへのアクセス許可がないと考えられるので、コードは SecurityPermission アンマネージコードを呼び出す権限を表すオブジェクトを作成し、オブジェクトのAssertメソッドを呼び出します。Because you believe that most of your callers will not have permission to access unmanaged code, your code then creates a SecurityPermission object that represents the right to call unmanaged code and calls the object's Assert method. 最後に、コードは C:\Text.txt を削除するアンマネージ Win32 関数を呼び出し、呼び出し元にコントロールを返します。Finally, it calls the unmanaged Win32 function to delete C:\Text.txt and returns control to the caller.

注意事項

そこで、アサートするためのアクセス許可によって保護されているリソースにアクセスするために自分のコードが他のコードによって使用される状況では、自分のコードでアサーションが使用されていないことを確認する必要があります。You must be sure that your code does not use assertions in situations where your code can be used by other code to access a resource that is protected by the permission you are asserting. たとえば、呼び出し元によってパラメーターとして指定された名前を持つファイルに書き込むコードでは、ファイルへの書き込みのためのFileIOPermissionをアサートしません。これは、コードがサードパーティによって悪用されるためです。For example, in code that writes to a file whose name is specified by the caller as a parameter, you would not assert the FileIOPermission for writing to files because your code would be open to misuse by a third party.

命令型セキュリティ構文を使用する場合、同じメソッド内の複数のアクセス許可でAssertメソッドを呼び出すと、セキュリティ例外がスローされます。When you use the imperative security syntax, calling the Assert method on multiple permissions in the same method causes a security exception to be thrown. 代わりに、 PermissionSetオブジェクトを作成し、呼び出す個々のアクセス許可を渡してから、 PermissionSetオブジェクトのAssertメソッドを呼び出します。Instead, you should create a PermissionSet object, pass it the individual permissions you want to invoke, and then call the Assert method on the PermissionSet object. 宣言セキュリティ構文を使用すると、 Assertメソッドを複数回呼び出すことができます。You can call the Assert method more than once when you use the declarative security syntax.

次の例は、 Assertメソッドを使用してセキュリティチェックをオーバーライドする宣言型の構文を示しています。The following example shows declarative syntax for overriding security checks using the Assert method. FileIOPermissionAttribute構文は、 SecurityAction 列挙と、アクセス許可が付与されるファイルまたはディレクトリの場所の2つの値を取ります。Notice that the FileIOPermissionAttribute syntax takes two values: a SecurityAction enumeration and the location of the file or directory to which permission is to be granted. 呼び出し元にAssert C:\Log.txt ファイルへのアクセス許可があるかどうかがチェックされない場合でも、Assert を呼び出すと、へのアクセスの要求が成功します。The call to Assert causes demands for access to C:\Log.txt to succeed, even though callers are not checked for permission to access the file.

Option Explicit  
Option Strict  
  
Imports System  
Imports System.IO  
Imports System.Security.Permissions  
  
Namespace LogUtil  
   Public Class Log  
      Public Sub New()  
  
      End Sub  
  
     <FileIOPermission(SecurityAction.Assert, All := "C:\Log.txt")> Public Sub
      MakeLog()  
         Dim TextStream As New StreamWriter("C:\Log.txt")  
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now) '  
         TextStream.Close()  
      End Sub  
   End Class  
End Namespace  
namespace LogUtil  
{  
   using System;  
   using System.IO;  
   using System.Security.Permissions;  
  
   public class Log  
   {  
      public Log()  
      {
      }
      [FileIOPermission(SecurityAction.Assert, All = @"C:\Log.txt")]  
      public void MakeLog()  
      {
         StreamWriter TextStream = new StreamWriter(@"C:\Log.txt");  
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now);  
         TextStream.Close();  
      }  
   }  
}

次のコードフラグメントは、 Assertメソッドを使用してセキュリティチェックをオーバーライドするための命令型の構文を示しています。The following code fragments show imperative syntax for overriding security checks using the Assert method. この例では、 FileIOPermissionオブジェクトのインスタンスが宣言されています。In this example, an instance of the FileIOPermission object is declared. コンストラクターには、許可されているアクセスの種類を定義するための FileIOPermissionAccess が渡され、その後にファイルの場所を説明する文字列が続きます Its constructor is passed FileIOPermissionAccess.AllAccess to define the type of access allowed, followed by a string describing the file's location. FileIOPermissionオブジェクトが定義されたら、そのAssertメソッドを呼び出して、セキュリティチェックをオーバーライドするだけで済みます。Once the FileIOPermission object is defined, you only need to call its Assert method to override the security check.

Option Explicit  
Option Strict  
Imports System  
Imports System.IO  
Imports System.Security.Permissions  
Namespace LogUtil  
   Public Class Log  
      Public Sub New()  
      End Sub 'New  
  
      Public Sub MakeLog()  
         Dim FilePermission As New FileIOPermission(FileIOPermissionAccess.AllAccess, "C:\Log.txt")  
         FilePermission.Assert()  
         Dim TextStream As New StreamWriter("C:\Log.txt")  
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now)  
         TextStream.Close()  
      End Sub  
   End Class  
End Namespace  
namespace LogUtil  
{  
   using System;  
   using System.IO;  
   using System.Security.Permissions;  
  
   public class Log  
   {  
      public Log()  
      {
      }
      public void MakeLog()  
      {  
         FileIOPermission FilePermission = new FileIOPermission(FileIOPermissionAccess.AllAccess,@"C:\Log.txt");
         FilePermission.Assert();  
         StreamWriter TextStream = new StreamWriter(@"C:\Log.txt");  
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now);  
         TextStream.Close();  
      }  
   }  
}  

関連項目See also