Поделиться через


Безопасность метода должна быть подмножеством типа

Обновлен: Ноябрь 2007

TypeName

MethodSecurityShouldBeASupersetOfType

CheckId

CA2114

Категория

Microsoft.Security

Критическое изменение

Критическое

Причина

Тип имеет декларативную безопасность, один из его методов имеет декларативную безопасность для такого же действия безопасности, причем действие безопасности отлично от Требования связывания и Требования наследования, а разрешения, проверяемые типом, не являются подмножеством разрешений, проверяемых методом.

Описание правила

Метод не должен иметь декларативную безопасность и на уровне метода, и на уровне типа для одного и того же действия. Эти две проверки не объединяются, применяется только запрос на уровне метода. Например, если тип запрашивает разрешение X и один из его методов запрашивает разрешение Y, код не должен иметь разрешение X для выполнения метода.

Устранение нарушений

Проверьте код и убедитесь, что оба действия необходимы. Если оба действия необходимы, то убедитесь, что действие на уровне метода включает безопасность, определенную на уровне типа. Например, если тип запрашивает разрешение X и его метод также должен запросить разрешение Y, метод должен явным образом запрашивать X и Y.

Отключение предупреждений

Можно безопасно отключать предупреждения этого правила, если для метода не требуется безопасность, указанная типом. Однако такие сценарии не являются общепринятыми; возможно, следует пересмотреть структуру программы.

Пример

В следующем примере показано применение разрешений среды для демонстрации опасности нарушения этого правила. В данном примере код приложения создает экземпляр безопасного типа перед отказом в разрешении, необходимом для этого типа. В обычном сценарии приложению потребуется другой способ получения экземпляра объекта.

В следующем примере библиотека запрашивает разрешение на запись для типа и разрешение на чтение для метода.

using System;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;

namespace SecurityRulesLibrary
{
   [EnvironmentPermissionAttribute(SecurityAction.Demand, Write="PersonalInfo")]
   public class MyClassWithTypeSecurity
   {
      [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
      [return:MarshalAs(UnmanagedType.Bool)]
      public static extern bool SetEnvironmentVariable(
         string lpName,
         string lpValue);

      // Constructor.
      public MyClassWithTypeSecurity(int year, int month, int day)
      {
         DateTime birthday = new DateTime(year, month, day);

         // Write out PersonalInfo environment variable.
         SetEnvironmentVariable("PersonalInfo",birthday.ToString());
      }

      [EnvironmentPermissionAttribute(SecurityAction.Demand, Read="PersonalInfo")]
      public string PersonalInformation ()
      { 
         // Read the variable.
         return Environment.GetEnvironmentVariable("PersonalInfo"); 
      }
   }
}

В следующем фрагменте кода демонстрируется уязвимость библиотеки из-за вызова метода, несмотря на то, что он не соответствует требованиям по безопасности на уровне типа.

using System;
using System.Security;
using System.Security.Permissions;
using SecurityRulesLibrary;

namespace TestSecRulesLibrary
{
   public class TestMethodLevelSecurity
   {
      MyClassWithTypeSecurity dataHolder;

      void RetrievePersonalInformation(string description) 
      {
         try 
         { 
            Console.WriteLine(
               "{0} Personal information: {1}", 
               description, dataHolder.PersonalInformation());
         }
         catch (SecurityException e) 
         {
            Console.WriteLine(
               "{0} Could not access personal information: {1}", 
               description, e.Message);
         }
      }

      [STAThread]
      public static void Main() 
      {
         TestMethodLevelSecurity me = new TestMethodLevelSecurity();

         me.dataHolder = new MyClassWithTypeSecurity(1964,06,16);

         // Local computer zone starts with all environment permissions.
         me.RetrievePersonalInformation("[All permissions]");

         // Deny the write permission required by the type.
         EnvironmentPermission epw = new EnvironmentPermission(
            EnvironmentPermissionAccess.Write,"PersonalInfo");
         epw.Deny();

         // Even though the type requires write permission, 
         // and you do not have it; you can get the data.
         me.RetrievePersonalInformation(
            "[No write permission (demanded by type)]");

         // Reset the permissions and try to get 
         // data without read permission.
         CodeAccessPermission.RevertAll();  

         // Deny the read permission required by the method.
         EnvironmentPermission epr = new EnvironmentPermission(
            EnvironmentPermissionAccess.Read,"PersonalInfo");
         epr.Deny();

         // The method requires read permission, and you
         // do not have it; you cannot get the data.
         me.RetrievePersonalInformation(
            "[No read permission (demanded by method)]");
      }
   }
}

В результате выполнения примера получается следующий результат:

[All permissions] Personal information: 6/16/1964 12:00:00 AM
[No write permission (demanded by type)] Personal information: 6/16/1964 12:00:00 AM
[No read permission (demanded by method)] Could not access personal information: Request failed.

См. также

Основные понятия

Требования наследования

Требования связывания

Другие ресурсы

Правила написания безопасного кода

Доступ к данным