주요 보안 개념

참고 항목

이 문서는 Windows에 적용됩니다.

ASP.NET Core에 대한 자세한 내용은 ASP.NET Core 보안 개요를 참조하세요.

.NET은 모바일 코드에 대한 보안 문제를 해결하고 구성 요소가 사용자에게 권한이 있는 작업을 결정할 수 있도록 지원하는 역할 기반 보안을 제공합니다.

형식 안전성 및 보안

형식 안전 코드는 액세스 권한이 부여된 메모리 위치에만 액세스합니다. 이 토론에서 형식 안전성은 특히 메모리 형식 안전성을 가리키며 보다 광범위한 의미의 형식 안전성과 혼동해서는 안 됩니다. 예를 들어 형식 안전 코드는 다른 개체의 전용 필드에서 값을 읽을 수 없습니다. 잘 정의된 허용되는 방식으로만 형식에 액세스합니다.

JIT(Just-In-Time) 컴파일 중에 선택적 검증 프로세스는 네이티브 기계어 코드로 JIT 컴파일될 메서드의 메타데이터 및 CIL(Common Intermediate Language)을 검사하여 형식이 안전한지 확인합니다. 코드에 검증을 건너뛸 수 있는 권한이 있으면 이 프로세스를 건너뜁니다. 검증에 대한 자세한 내용은 관리되는 실행 프로세스를 참조하세요.

형식 안전성 검증은 관리 코드를 실행하기 위한 필수 사항이 아니지만 형식 안전성은 어셈블리 격리 및 보안 적용에서 중요한 역할을 합니다. 코드 형식이 안전한 경우 공용 언어 런타임에서 어셈블리를 서로 완전히 격리할 수 있습니다. 이 격리는 어셈블리가 서로 부정적인 영향을 줄 수 없도록 하며 애플리케이션 안정성을 향상시킵니다. 형식이 안전한 구성 요소는 서로 다른 수준에서 신뢰된 경우에도 동일한 프로세스에서 안전하게 실행할 수 있습니다. 코드 형식이 안전하지 않은 경우 원치 않는 부작용이 발생할 수 있습니다. 예를 들면, 관리 코드가 네이티브(비관리) 코드로 호출되어 부정적인 작업을 수행하는 것을 런타임에서 방지할 수 없습니다. 코드 형식이 안전하면 런타임의 보안 적용 메커니즘에서 권한이 없을 경우 네이티브 코드에 액세스하지 않도록 합니다. 형식이 안전하지 않은 모든 코드를 실행하려면 전달된 열거형 멤버 SkipVerification과 함께 SecurityPermission이 부여되어야 합니다.

참고 항목

CAS(코드 액세스 보안)는 .NET Framework 및 .NET의 모든 버전에서 더 이상 사용되지 않습니다. 최신 버전의 .NET은 CAS 주석을 준수하지 않으며 CAS 관련 API를 사용하는 경우 오류가 발생합니다. 개발자는 보안 작업을 수행하는 대체 수단을 찾아야 합니다.

주 서버

보안 주체는 사용자의 ID 및 역할을 나타내고 사용자 대신 역할을 수행합니다. .NET의 역할 기반 보안은 세 가지 종류의 보안 주체를 지원합니다.

  • 일반 보안 주체는 Windows 사용자 및 역할과 독립적으로 존재하는 사용자와 역할을 나타냅니다.

  • Windows 보안 주체는 Windows 사용자와 해당 역할(또는 해당 Windows 그룹)을 나타냅니다. Windows 보안 주체는 다른 사용자를 가장할 수 있습니다. 이는 해당 사용자에게 속하는 ID를 제공하는 동안 보안 주체가 사용자 대신 리소스에 액세스할 수 있음을 의미합니다.

  • 해당 특정 애플리케이션에 필요한 방식으로 애플리케이션에서 사용자 지정 보안 주체를 정의할 수 있습니다. 보안 주체의 ID 및 역할의 기본 개념을 확장할 수 있습니다.

자세한 내용은 Principal 개체 및 Identity 개체를 참조하세요.

인증

인증은 사용자 자격 증명을 검사하고 일부 권한에 대해 해당 자격 증명의 유효성을 검사하여 보안 주체의 ID를 찾고 확인하는 프로세스입니다. 인증 중에 얻은 정보를 코드에서 직접 사용할 수 있습니다. .NET 역할 기반 보안을 사용하여 현재 사용자를 인증하고 해당 보안 주체가 코드에 액세스할 수 있도록 할지 여부를 결정할 수도 있습니다. 특정 역할에 대해 보안 주체를 인증하는 방법의 예는 WindowsPrincipal.IsInRole 메서드 오버로드를 참조하세요. 예를 들어 WindowsPrincipal.IsInRole(String) 오버로드를 사용하여 현재 사용자가 Administrators 그룹의 멤버인지 확인할 수 있습니다.

오늘날 다양한 인증 메커니즘이 사용되며 그중 다수는 .NET 역할 기반 보안과 함께 사용할 수 있습니다. 가장 일반적으로 사용되는 메커니즘 중 일부는 기본, 다이제스트, Passport, 운영 체제(예: NTLM 또는 Kerberos) 또는 애플리케이션 정의 메커니즘입니다.

예시

다음 예제에서는 활성 보안 주체가 관리자여야 합니다. name 매개 변수는 null이므로 관리자인 모든 사용자가 요구를 전달할 수 있습니다.

참고 항목

Windows Vista에서는 UAC(사용자 계정 컨트롤)가 사용자 권한을 결정합니다. 기본 제공 Administrators 그룹의 멤버인 경우 두 개의 런타임 액세스 토큰(표준 사용자 액세스 토큰 및 관리자 액세스 토큰)이 할당됩니다. 기본적으로 표준 사용자 역할이 지정됩니다. 관리자 권한이 필요한 코드를 실행하려면 먼저 표준 사용자에서 관리자로 권한을 높여야 합니다. 애플리케이션 아이콘을 마우스 오른쪽 단추로 클릭하고 관리자로 실행하도록 지정하여 애플리케이션을 시작하면 이 작업을 수행할 수 있습니다.

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

다음 예제에서는 보안 주체 및 보안 주체가 사용할 수 있는 역할의 ID를 확인하는 방법을 보여 줍니다. 이 예제의 애플리케이션은 현재 사용자가 애플리케이션을 사용하도록 허용하는 역할에 있는지 확인하기 위한 것일 수 있습니다.

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

권한 부여

권한 부여는 보안 주체가 요청된 작업을 수행할 수 있는지 여부를 확인하는 프로세스입니다. 권한 부여는 인증 후 발생하며 보안 주체의 ID 및 역할에 대한 정보를 사용하여 보안 주체가 액세스할 수 있는 리소스를 확인합니다. .NET 역할 기반 보안을 사용하여 권한 부여를 구현할 수 있습니다.

참고 항목