Conceitos principais de segurança

Observação

Este artigo aplica-se ao Windows.

Para obter informações sobre o ASP.NET Core, consulte a Visão geral da segurança do ASP.NET Core.

O .NET oferece segurança baseada em função, para ajudar a resolver as preocupações de segurança sobre o código móvel e dar suporte para permitir que os componentes determinem o que os usuários estão autorizados a fazer.

Segurança de tipos e proteção

O código fortemente tipado acessa apenas os locais de memória que está autorizado a acessar. (Para essa discussão, a segurança de tipos refere-se especificamente à segurança de tipos de memória e não deve ser confundida com a segurança de tipos em um aspecto mais abrangente.) Por exemplo, o código fortemente tipado não pode ler os valores dos campos privados de outro objeto. Ele acessa os tipos apenas de maneiras bem definidas e permitidas.

Durante a compilação JIT, um processo de verificação opcional examina os metadados e a CIL (Linguagem Intermediária Comum) de um método a ser submetido à compilação JIT em código de computador nativo, para verificar se eles são fortemente tipados. Esse processo será ignorado, se o código tiver permissão para ignorar a verificação. Para obter mais informações sobre verificação, confira Processo de Execução Gerenciada.

Embora a verificação da segurança de tipos não seja obrigatória para executar o código gerenciado, a segurança de tipos desempenha um papel fundamental no isolamento do assembly e na imposição de segurança. Quando o código é fortemente tipado, o Common Language Runtime pode isolar completamente os assemblies uns dos outros. Esse isolamento ajuda a garantir que os assemblies não afetem negativamente uns aos outros e aumenta a confiabilidade do aplicativo. Os componentes fortemente tipados podem ser executados com segurança no mesmo processo, mesmo que sejam confiáveis em níveis diferentes. Quando o código não é fortemente tipado, efeitos colaterais indesejados podem ocorrer. Por exemplo, o runtime não pode impedir que o código gerenciado chame o código nativo (não gerenciado) e execute operações mal-intencionadas. Quando o código é fortemente tipado, o mecanismo de imposição de segurança do runtime garante que ele não acesse o código nativo, a menos que tenha permissão para tanto. Todo o código que não fortemente tipado deve receber SecurityPermission com o membro de enumeração aprovado SkipVerification para execução.

Observação

O CAS (Segurança de Acesso do Código) foi preterido em todas as versões do .NET Framework e do .NET. As versões recentes do .NET não aceitam anotações de CAS e produzem erros caso as APIs relacionadas ao CAS sejam usadas. Os desenvolvedores devem buscar meios alternativos de realizar tarefas de segurança.

Principal

Uma entidade de segurança representa a identidade e a função de um usuário e atua em nome do usuário. A segurança baseada em função no .NET permite três tipos de entidades de segurança:

  • As entidades de segurança genéricas representam usuários e funções que existem independentemente de usuários e funções do Windows.

  • As entidades de segurança do Windows representam usuários do Windows e suas funções (ou seus grupos do Windows). Uma entidade de segurança do Windows pode representar outro usuário, o que significa que a entidade de segurança pode acessar um recurso em nome de um usuário, ao apresentar a identidade que pertence a esse usuário.

  • As entidades de segurança personalizadas podem ser definidas por um aplicativo de qualquer forma necessária para esse aplicativo específico. Elas podem estender as noções básicas da identidade e das funções da entidade de segurança.

Para obter mais informações, confira Objetos de entidade de segurança e de identidade.

Autenticação

Autenticação é o processo de descobrir e verificar a identidade de uma entidade de segurança, examinando as credenciais do usuário e validando essas credenciais em relação a determinada autoridade. As informações obtidas durante a autenticação podem ser diretamente utilizáveis pelo código. Você também pode usar a segurança baseada em função do .NET, para autenticar o usuário atual e determinar se deseja permitir que essa entidade de segurança acesse o código. Confira as sobrecargas do método WindowsPrincipal.IsInRole para obter exemplos de como autenticar a entidade de segurança para funções específicas. Por exemplo, você pode usar a sobrecarga WindowsPrincipal.IsInRole(String) para determinar se o usuário atual é membro do grupo Administradores.

Uma variedade de mecanismos de autenticação são usados atualmente. Muitos deles podem ser usados com a segurança baseada em função do .NET. Alguns dos mecanismos mais usados são mecanismos básicos, digest, Passport, sistema operacional (como NTLM ou Kerberos) ou definidos pelo aplicativo.

Exemplo

O exemplo a seguir exige que a entidade de segurança ativa seja um administrador. O parâmetro name é null, o que permite que qualquer usuário que seja um administrador passe a demanda.

Observação

No Windows Vista, o UAC (Controle de Conta de Usuário) determina os privilégios de um usuário. Se for um membro do grupo Administradores Internos, você receberá dois tokens de acesso do tempo de execução: um token de acesso do usuário padrão e um token de acesso do administrador. Por padrão, você está na função de usuário padrão. Para executar o código que exige que você seja um administrador, você deve primeiro elevar os privilégios de usuário padrão para administrador. Você pode fazer isso ao iniciar um aplicativo, clicando com o botão direito do mouse no ícone do aplicativo e indicando que você deseja executar como administrador.

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

O exemplo a seguir demonstra como determinar a identidade da entidade de segurança e as funções disponíveis para a entidade de segurança. Um aplicativo deste exemplo pode ser usado para confirmar que o usuário atual está em uma função que você permite que use o aplicativo.

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

Autorização

Autorização é o processo de determinar se uma entidade de segurança tem permissão para executar uma ação solicitada. A autorização ocorre após a autenticação e usa informações sobre a identidade e as funções da entidade de segurança, para determinar quais recursos a entidade de segurança pode acessar. Você pode usar a segurança baseada em função do .NET para implementar a autorização.

Confira também