Principais conceitos de segurança
Nota
Este artigo aplica-se ao Windows.
Para obter informações sobre o ASP.NET Core, consulte Visão geral do ASP.NET Core Security.
O .NET oferece segurança baseada em função para ajudar a resolver preocupações de segurança sobre código móvel e fornecer suporte que permite que os componentes determinem o que os usuários estão autorizados a fazer.
Tipo de segurança e proteção
O código Type-Safe acessa apenas os locais de memória que está autorizado a acessar. (Para esta discussão, a segurança do tipo refere-se especificamente à segurança do tipo de memória e não deve ser confundida com a segurança do tipo em um aspeto mais amplo.) Por exemplo, o código type-safe não pode ler valores de campos privados de outro objeto. Ele acessa tipos apenas de maneiras bem definidas e permitidas.
Durante a compilação just-in-time (JIT), um processo de verificação opcional examina os metadados e a linguagem intermediária comum (CIL) de um método a ser compilado em código de máquina nativo para verificar se eles são seguros para tipo. Esse processo será ignorado se o código tiver permissão para ignorar a verificação. Para obter mais informações sobre verificação, consulte Processo de execução gerenciado.
Embora a verificação da segurança do tipo não seja obrigatória para executar o código gerenciado, a segurança do tipo desempenha um papel crucial no isolamento da montagem e na aplicação da segurança. Quando o código é tipo seguro, o common language runtime pode isolar completamente os assemblies uns dos outros. Esse isolamento ajuda a garantir que os assemblies não possam afetar negativamente uns aos outros e aumenta a confiabilidade do aplicativo. Os componentes seguros para tipos podem ser executados com segurança no mesmo processo, mesmo que sejam confiáveis em níveis diferentes. Quando o código não é seguro tipo, efeitos colaterais indesejados podem ocorrer. Por exemplo, o tempo de execução não pode impedir que o código gerenciado chame o código nativo (não gerenciado) e execute operações maliciosas. Quando o código é tipo seguro, o mecanismo de imposição de segurança do tempo de execução garante que ele não acesse o código nativo, a menos que tenha permissão para fazê-lo. Todo o código que não é tipo seguro deve ter sido concedido SecurityPermission com o membro SkipVerification enum passado para ser executado.
Nota
O CAS (Code Access Security) foi preterido em todas as versões do .NET Framework e do .NET. As versões recentes do .NET não respeitam as anotações do CAS e produzem erros se as APIs relacionadas ao CAS forem usadas. Os desenvolvedores devem procurar meios alternativos de realizar tarefas de segurança.
Principal
Uma entidade representa a identidade e a função de um usuário e age em nome do usuário. A segurança baseada em função no .NET oferece suporte a três tipos de entidades:
As entidades genéricas representam usuários e funções que existem independentemente dos usuários e funções do Windows.
As entidades do Windows representam os 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 enquanto apresenta a identidade que pertence a esse usuário.
Os principais personalizados podem ser definidos por um aplicativo de qualquer maneira que seja necessária para esse aplicativo específico. Podem alargar a noção básica da identidade e dos papéis do comitente.
Para obter mais informações, consulte Objetos principal e de identidade.
Autenticação
A 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 alguma autoridade. As informações obtidas durante a autenticação são diretamente utilizáveis pelo seu 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 deve permitir que essa entidade acesse seu código. Consulte as sobrecargas do método para obter exemplos de como autenticar a entidade de WindowsPrincipal.IsInRole segurança para funções específicas. Por exemplo, você pode usar a WindowsPrincipal.IsInRole(String) sobrecarga para determinar se o usuário atual é membro do grupo Administradores.
Uma variedade de mecanismos de autenticação são usados atualmente, muitos dos quais podem ser usados com segurança baseada em função .NET. Alguns dos mecanismos mais usados são básico, digest, Passport, sistema operacional (como NTLM ou Kerberos) ou mecanismos definidos pelo aplicativo.
Exemplo
O exemplo a seguir requer que a entidade de segurança ativa seja um administrador. O name
parâmetro é null
, que permite que qualquer usuário que seja administrador passe a demanda.
Nota
No Windows Vista, o Controle de Conta de Usuário (UAC) determina os privilégios de um usuário. Se você for membro do grupo Administradores internos, receberá dois tokens de acesso em tempo de execução: um token de acesso de usuário padrão e um token de acesso de administrador. Por padrão, você está na função de usuário padrão. Para executar o código que requer que você seja um administrador, você deve primeiro elevar seus 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 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 do principal e as funções disponíveis para o principal. Uma aplicação deste exemplo pode ser confirmar que o usuário atual está em uma função que você permite usar seu 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
A 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.