Основные понятия безопасности

Примечание.

Эта статья применима к Windows.

Дополнительные сведения о ASP.NET Core см. в разделе "Общие сведения о ASP.NET основной безопасности".

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

Безопасность типа и безопасность

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

Во время JIT-компиляции необязательный процесс проверки проверяет метаданные и общий промежуточный язык метода для JIT-компиляции в машинный код, чтобы убедиться, что они являются безопасными. Этот процесс не выполняется, если код имеет разрешение на пропуск проверки. Дополнительные сведения о проверке см. в разделе Процесс управляемого выполнения.

Хотя проверка безопасности типа не обязательна для запуска управляемого кода, безопасность типа играет ключевую роль в изоляции сборок и обеспечении безопасности. Если код является типобезопасным, среда CLR может полностью изолировать сборки друг от друга. Эта изоляция помогает обеспечить отсутствие отрицательного влияния сборок друг на друга и повышает надежность приложений. Компоненты с безопасностью типа могут безопасно выполняться в одном процессе, даже если они имеют доверие на разных уровнях. Если код не является типобезопасным, могут возникать нежелательные побочные эффекты. Например, среда выполнения не может препятствовать вызову машинного (неуправляемого) кода со стороны управляемого кода и выполнению управляемым кодом нежелательных операций. Если код является типобезопасным, механизм обеспечения безопасности среды выполнения гарантирует, что он не будет иметь доступ к машинному коду при отсутствии соответствующего разрешения. Чтобы код без безопасности типа мог запускаться, ему необходимо предоставить разрешение SecurityPermission с переданным элементом перечисления SkipVerification.

Примечание.

Безопасность доступа к коду (CAS) устарела во всех версиях платформа .NET Framework и .NET. Последние версии .NET не учитывают заметки CAS и создают ошибки, если используются API, связанные с CAS. Разработчики должны искать альтернативные средства выполнения задач безопасности.

Субъект

Участник представляет удостоверение и роль пользователя и действует от имени пользователя. Безопасность на основе ролей в .NET поддерживает три типа субъектов:

  • Универсальные участники представляют пользователей и роли, которые существуют независимо от пользователей и ролей Windows.

  • Участники Windows представляют пользователей Windows и их роли (или их группы Windows). Участник Windows может олицетворять другого пользователя, что означает, что этому участнику разрешен доступ к ресурсу от имени пользователя при предоставлении удостоверения, которое принадлежит этому пользователю.

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

Дополнительные сведения см. в разделе Объекты Principal и Identity.

Проверка подлинности

Проверка подлинности (аутентификация) — это процесс обнаружения и проверки удостоверения участника путем проверки учетных данных пользователя и проверки этих учетных данных в отношении некоторого центра сертификации. Сведения, полученные во время проверки подлинности, можно напрямую использовать в коде. Вы также можете использовать безопасность на основе ролей .NET для проверки подлинности текущего пользователя и определить, разрешать ли субъекту доступ к коду. Примеры проверки подлинности участника для конкретных ролей см. в описании перегрузок метода WindowsPrincipal.IsInRole. Например, можно использовать перегрузку WindowsPrincipal.IsInRole(String), чтобы определить, является ли текущий пользователь членом группы «Администраторы».

Сегодня используются различные механизмы проверки подлинности, многие из которых можно использовать с безопасностью на основе ролей .NET. Некоторые из наиболее часто используемых механизмов — это обычная проверка подлинности, дайджест-проверка подлинности, проверка подлинности по паспорту, проверка подлинности операционной системы (например, NTLM или Kerberos) или механизмы, определяемые приложением.

Пример

Следующий пример требует, чтобы активный участник был администратором. Параметр name имеет значение null, что позволяет любому пользователю с правами администратора проходить требование.

Примечание.

В Windows Vista привилегии пользователя определяются контролем учетных записей (UAC). Члену встроенной группы "Администраторы" присваивается два маркера доступа на время выполнения: маркер доступа обычного пользователя и маркер доступа администратора. По умолчанию назначена роль обычного пользователя. Чтобы выполнить код, требующий прав администратора, необходимо сначала повысить права от прав стандартного пользователя до прав администратора. Это можно сделать при запуске приложения, , щелкнув значок приложения правой кнопкой мыши и указав, что приложение должно запускаться от имени администратора.

using namespace System;
using namespace System::Security;
using namespace System::Security::Permissions;
using namespace System::Security::Policy;
using namespace System::Security::Principal;

int main(array<System::String ^> ^args)
{
    System::String^ null;
    AppDomain::CurrentDomain->SetPrincipalPolicy(PrincipalPolicy::WindowsPrincipal);
    PrincipalPermission^ principalPerm = gcnew PrincipalPermission(null, "Administrators" );
      principalPerm->Demand();
      Console::WriteLine("Demand succeeded");
    return 0;
}
using System;
using System.Threading;
using System.Security.Permissions;
using System.Security.Principal;

class SecurityPrincipalDemo
{

    public static void Main()
    {
        AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
        PrincipalPermission principalPerm = new PrincipalPermission(null, "Administrators");
        principalPerm.Demand();
        Console.WriteLine("Demand succeeded.");
    }
}
Imports System.Threading
Imports System.Security.Permissions
Imports System.Security.Principal



Class SecurityPrincipalDemo


    Public Shared Sub Main()
        AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
        Dim principalPerm As New PrincipalPermission(Nothing, "Administrators")
        principalPerm.Demand()
        Console.WriteLine("Demand succeeded.")

    End Sub
End Class

Следующий пример демонстрирует, как определить удостоверение участника и доступные для него роли. Приложение в этом примере должно проверять, что текущий пользователь имеет роль, которая позволяет использовать приложение.

public:
   static void DemonstrateWindowsBuiltInRoleEnum()
   {
      AppDomain^ myDomain = Thread::GetDomain();

      myDomain->SetPrincipalPolicy( PrincipalPolicy::WindowsPrincipal );
      WindowsPrincipal^ myPrincipal = dynamic_cast<WindowsPrincipal^>(Thread::CurrentPrincipal);

      Console::WriteLine( "{0} belongs to: ", myPrincipal->Identity->Name );

      Array^ wbirFields = Enum::GetValues( WindowsBuiltInRole::typeid );

      for each ( Object^ roleName in wbirFields )
      {
         try
         {
            Console::WriteLine( "{0}? {1}.", roleName,
               myPrincipal->IsInRole(  *dynamic_cast<WindowsBuiltInRole^>(roleName) ) );
         }
         catch ( Exception^ ) 
         {
            Console::WriteLine( "{0}: Could not obtain role for this RID.",
               roleName );
         }
      }
   }
using System;
using System.Threading;
using System.Security.Permissions;
using System.Security.Principal;

class SecurityPrincipalDemo
{
    public static void DemonstrateWindowsBuiltInRoleEnum()
    {
        AppDomain myDomain = Thread.GetDomain();

        myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
        WindowsPrincipal myPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal;
        Console.WriteLine("{0} belongs to: ", myPrincipal.Identity.Name.ToString());
        Array wbirFields = Enum.GetValues(typeof(WindowsBuiltInRole));
        foreach (object roleName in wbirFields)
        {
            try
            {
                // Cast the role name to a RID represented by the WindowsBuildInRole value.
                Console.WriteLine("{0}? {1}.", roleName,
                    myPrincipal.IsInRole((WindowsBuiltInRole)roleName));
                Console.WriteLine("The RID for this role is: " + ((int)roleName).ToString());
            }
            catch (Exception)
            {
                Console.WriteLine("{0}: Could not obtain role for this RID.",
                    roleName);
            }
        }
        // Get the role using the string value of the role.
        Console.WriteLine("{0}? {1}.", "Administrators",
            myPrincipal.IsInRole("BUILTIN\\" + "Administrators"));
        Console.WriteLine("{0}? {1}.", "Users",
            myPrincipal.IsInRole("BUILTIN\\" + "Users"));
        // Get the role using the WindowsBuiltInRole enumeration value.
        Console.WriteLine("{0}? {1}.", WindowsBuiltInRole.Administrator,
           myPrincipal.IsInRole(WindowsBuiltInRole.Administrator));
        // Get the role using the WellKnownSidType.
        SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
        Console.WriteLine("WellKnownSidType BuiltinAdministratorsSid  {0}? {1}.", sid.Value, myPrincipal.IsInRole(sid));
    }

    public static void Main()
    {
        DemonstrateWindowsBuiltInRoleEnum();
    }
}
Imports System.Threading
Imports System.Security.Permissions
Imports System.Security.Principal

Class SecurityPrincipalDemo

    Public Shared Sub DemonstrateWindowsBuiltInRoleEnum()
        Dim myDomain As AppDomain = Thread.GetDomain()

        myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
        Dim myPrincipal As WindowsPrincipal = CType(Thread.CurrentPrincipal, WindowsPrincipal)
        Console.WriteLine("{0} belongs to: ", myPrincipal.Identity.Name.ToString())
        Dim wbirFields As Array = [Enum].GetValues(GetType(WindowsBuiltInRole))
        Dim roleName As Object
        For Each roleName In wbirFields
            Try
                ' Cast the role name to a RID represented by the WindowsBuildInRole value.
                Console.WriteLine("{0}? {1}.", roleName, myPrincipal.IsInRole(CType(roleName, WindowsBuiltInRole)))
                Console.WriteLine("The RID for this role is: " + Fix(roleName).ToString())

            Catch
                Console.WriteLine("{0}: Could not obtain role for this RID.", roleName)
            End Try
        Next roleName
        ' Get the role using the string value of the role.
        Console.WriteLine("{0}? {1}.", "Administrators", myPrincipal.IsInRole("BUILTIN\" + "Administrators"))
        Console.WriteLine("{0}? {1}.", "Users", myPrincipal.IsInRole("BUILTIN\" + "Users"))
        ' Get the role using the WindowsBuiltInRole enumeration value.
        Console.WriteLine("{0}? {1}.", WindowsBuiltInRole.Administrator, myPrincipal.IsInRole(WindowsBuiltInRole.Administrator))
        ' Get the role using the WellKnownSidType.
        Dim sid As New SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, Nothing)
        Console.WriteLine("WellKnownSidType BuiltinAdministratorsSid  {0}? {1}.", sid.Value, myPrincipal.IsInRole(sid))

    End Sub

    Public Shared Sub Main()
        DemonstrateWindowsBuiltInRoleEnum()

    End Sub
End Class

Авторизация

Авторизация — это процесс определения, разрешено ли участнику выполнять запрошенное действие. Авторизация происходит после проверки подлинности и использует сведения об удостоверении и ролях участника, чтобы определить, к каким ресурсам имеет доступ этот участник. Для реализации авторизации можно использовать безопасность на основе ролей .NET.

См. также