Depurar erros de autenticação do Windows

Quando a autenticação do Windows é usada como um mecanismo de segurança, a interface SSPI cuida dos processos de segurança. Quando ocorrem erros de segurança na camada do SSPI, eles são exibidos pelo WCF (Windows Communication Foundation). Este tópico fornece uma estrutura e um conjunto de perguntas para ajudar a diagnosticar os erros.

Para ter uma visão geral do protocolo Kerberos, confira Explicação sobre o Kerberos. Para ter uma visão geral do SSPI, confira SSPI.

Para a autenticação do Windows, o WCF normalmente usa o SSP (Provedor de Suporte à Segurança) Negotiate, que executa a autenticação mútua Kerberos entre o cliente e o serviço. Se o protocolo Kerberos não estiver disponível, por padrão, o WCF retornará ao NTLM (NT LAN Manager). No entanto, você pode configurar o WCF para usar apenas o protocolo Kerberos (e gerar uma exceção se o Kerberos não estiver disponível). Você também pode configurar o WCF para usar formas restritas do protocolo Kerberos.

Metodologia de depuração

O método básico é o seguinte:

  1. Determine se você está usando a autenticação do Windows. Se você estiver usando qualquer outro esquema, este tópico não se aplicará.

  2. Se você tiver certeza de que está usando a autenticação do Windows, determine se a configuração do WCF usa o Kerberos direto ou o Negotiate.

  3. Depois de determinar se a configuração está usando o protocolo Kerberos ou o NTLM, você poderá entender as mensagens de erro no contexto correto.

Disponibilidade do protocolo Kerberos e do NTLM

O SSP Kerberos exige que um controlador de domínio funcione como o KDC (centro de distribuição de chaves) do Kerberos. O protocolo Kerberos só estará disponível quando o cliente e o serviço estiverem usando identidades de domínio. Em outras combinações de contas, o NTLM é usado, conforme resumido na tabela a seguir.

Os cabeçalhos da tabela mostram os possíveis tipos de contas usados pelo servidor. A coluna à esquerda mostra os possíveis tipos de contas usados pelo cliente.

Usuário Local Sistema Local Usuário do Domínio Computador do Domínio
Usuário Local NTLM NTLM NTLM NTLM
Sistema Local NTLM anônimo NTLM anônimo NTLM anônimo NTLM anônimo
Usuário do Domínio NTLM NTLM Kerberos Kerberos
Computador do Domínio NTLM NTLM Kerberos Kerberos

Especificamente, os quatro tipos de contas incluem:

  • Usuário Local: perfil de usuário somente do computador. Por exemplo: MachineName\Administrator ou MachineName\ProfileName.

  • Sistema Local: o SISTEMA de conta interno em um computador que não está ingressado em um domínio.

  • Usuário do Domínio: uma conta de usuário em um domínio do Windows. Por exemplo: DomainName\ProfileName.

  • Computador do Domínio: um processo com a identidade do computador em execução em um computador ingressado em um domínio do Windows. Por exemplo: MachineName\Network Service.

Observação

A credencial de serviço é capturada quando o método Open da classe ServiceHost é chamado. A credencial do cliente é lida sempre que o cliente envia uma mensagem.

Problemas comuns de autenticação do Windows

Esta seção discute alguns problemas comuns de autenticação do Windows e as possíveis soluções.

Protocolo Kerberos

Problemas de SPN/UPN com o protocolo Kerberos

Quando a autenticação do Windows é usada e o protocolo Kerberos é usado ou negociado pelo SSPI, a URL usada pelo ponto de extremidade do cliente precisa incluir o nome de domínio totalmente qualificado do host do serviço na URL de serviço. Isso pressupõe que a conta na qual o serviço está sendo executado tenha acesso à chave SPN (nome da entidade de serviço) do computador (padrão) que é criada quando o computador é adicionado ao domínio do Active Directory, o que é mais comumente feito com a execução do serviço na conta do Serviço de Rede. Se o serviço não tiver acesso à chave SPN do computador, você precisará fornecer o SPN correto ou o UPN (nome de entidade de usuário) da conta na qual o serviço está sendo executado na identidade do ponto de extremidade do cliente. Para obter mais informações sobre como o WCF funciona com o SPN e o UPN, confira Identidade de serviço e autenticação.

Em cenários de balanceamento de carga, como Web farms ou Web gardens, uma prática comum é definir uma conta exclusiva para cada aplicativo, atribuir um SPN a essa conta e garantir que todos os serviços do aplicativo sejam executados nessa conta.

Para obter um SPN para a conta do serviço, você precisa ser um administrador de domínio do Active Directory. Para obter mais informações, confira Suplemento técnico do Kerberos para o Windows.

O Protocolo Kerberos Direto exige que o serviço seja executado em uma conta do computador do domínio

Isso ocorre quando a propriedade ClientCredentialType é definida como Windows e a propriedade NegotiateServiceCredential é definida como false, conforme mostrado no código a seguir.

WSHttpBinding b = new WSHttpBinding();
// By default, the WSHttpBinding uses Windows authentication
// and Message mode.
b.Security.Message.NegotiateServiceCredential = false;
Dim b As New WSHttpBinding()
' By default, the WSHttpBinding uses Windows authentication 
' and Message mode.
b.Security.Message.NegotiateServiceCredential = False

Para corrigir isso, execute o serviço usando uma conta do Computador do Domínio, como o Serviço de Rede, em um computador ingressado no domínio.

A delegação exige a negociação de credenciais

Para usar o protocolo de autenticação Kerberos com a delegação, você precisa implementar o protocolo Kerberos com a negociação de credenciais (às vezes chamado de Kerberos "de vários segmentos" ou "de várias etapas"). Se você implementar a autenticação Kerberos sem a negociação de credenciais (às vezes chamada de Kerberos "de processo único" ou "de segmento único"), uma exceção será gerada.

Para implementar o Kerberos com a negociação de credenciais, siga as seguintes etapas:

  1. Implemente a delegação definindo AllowedImpersonationLevel como Delegation.

  2. Exija a negociação do SSPI:

    1. Se você estiver usando associações padrão, defina a propriedade NegotiateServiceCredential como true.

    2. Se estiver usando associações personalizadas, defina o atributo AuthenticationMode do elemento Security como SspiNegotiated.

  3. Exija que a negociação do SSPI use o Kerberos, não permitindo o uso do NTLM:

    1. Faça isso no código, com a seguinte instrução: ChannelFactory.Credentials.Windows.AllowNtlm = false

    2. Ou, então, faça isso no arquivo de configuração definindo o atributo allowNtlm como false. Esse atributo está contido nas <janelas>.

Protocolo NTLM

O SSP Negotiate retorna para o NTLM, mas o NTLM está desabilitado

A propriedade AllowNtlm está definida como false, o que faz com que o WCF (Windows Communication Foundation) faça um melhor esforço para gerar uma exceção se o NTLM for usado. A definição dessa propriedade como false pode não impedir que as credenciais do NTLM sejam enviadas pela rede.

Veja a seguir como desabilitar o fallback para o NTLM.

CalculatorClient cc = new
    CalculatorClient("WSHttpBinding_ICalculator");
cc.ClientCredentials.Windows.AllowNtlm = false;
Dim cc As New CalculatorClient("WSHttpBinding_ICalculator")
cc.ClientCredentials.Windows.AllowNtlm = False

Falha no logon do NTLM

As credenciais do cliente não são válidas no serviço. Verifique se o nome de usuário e a senha estão definidos corretamente e se eles correspondem a uma conta conhecida pelo computador em que o serviço está em execução. O NTLM usa as credenciais especificadas para fazer logon no computador do serviço. Embora as credenciais possam ser válidas no computador em que o cliente está em execução, esse logon falhará se as credenciais não forem válidas no computador do serviço.

O logon anônimo do NTLM ocorre, mas os logons anônimos estão desabilitados por padrão

Quando um cliente é criado, a propriedade AllowedImpersonationLevel é definida como Anonymous, conforme mostrado no exemplo a seguir, mas, por padrão, o servidor não permite logons anônimos. Isso ocorre porque o valor padrão da propriedade AllowAnonymousLogons da classe WindowsServiceCredential é false.

O código do cliente a seguir tenta habilitar logons anônimos (observe que a propriedade padrão é Identification).

CalculatorClient cc =
    new CalculatorClient("WSHttpBinding_ICalculator");
cc.ClientCredentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Anonymous;
Dim cc As New CalculatorClient("WSHttpBinding_ICalculator")
cc.ClientCredentials.Windows.AllowedImpersonationLevel = _
System.Security.Principal.TokenImpersonationLevel.Anonymous

O código de serviço a seguir altera o padrão para habilitar logons anônimos pelo servidor.

Uri httpUri = new Uri("http://localhost:8000/");
ServiceHost sh = new ServiceHost(typeof(Calculator), httpUri);
sh.Credentials.WindowsAuthentication.AllowAnonymousLogons = true;
Dim httpUri As New Uri("http://localhost:8000/")
Dim sh As New ServiceHost(GetType(Calculator), httpUri)
sh.Credentials.WindowsAuthentication.AllowAnonymousLogons = True

Para obter mais informações sobre a representação, confira Delegação e representação.

Como alternativa, o cliente está em execução como um serviço Windows, usando a conta interna SISTEMA.

Outros Problemas

As credenciais do cliente não estão definidas corretamente

A autenticação do Windows usa a instância WindowsClientCredential retornada pela propriedade ClientCredentials da classe ClientBase<TChannel>, não pela UserNamePasswordClientCredential. Veja a seguir um exemplo incorreto.

CalculatorClient cc = new
    CalculatorClient("WSHttpBinding_ICalculator");
cc.ClientCredentials.UserName.UserName = GetUserName(); // wrong!
cc.ClientCredentials.UserName.Password = GetPassword(); // wrong!
Dim cc As New CalculatorClient("WSHttpBinding_ICalculator")
cc.ClientCredentials.UserName.UserName = GetUserName() ' wrong!
cc.ClientCredentials.UserName.Password = GetPassword() ' wrong!

Veja a seguir um exemplo correto.

CalculatorClient cc = new
    CalculatorClient("WSHttpBinding_ICalculator");
// This code returns the WindowsClientCredential type.
cc.ClientCredentials.Windows.ClientCredential.UserName = GetUserName();
cc.ClientCredentials.Windows.ClientCredential.Password = GetPassword();
Dim cc As New CalculatorClient("WSHttpBinding_ICalculator")
' This code returns the WindowsClientCredential type.            
cc.ClientCredentials.Windows.ClientCredential.UserName = GetUserName()
cc.ClientCredentials.Windows.ClientCredential.Password = GetPassword()

O SSPI não está disponível

Os seguintes sistemas operacionais não dão suporte à autenticação do Windows quando usados como um servidor: Windows XP Home Edition, Windows XP Media Center Edition e edições do Windows Vista Home.

Desenvolvimento e implantação com identidades diferentes

Se você desenvolver seu aplicativo em um computador e implantá-lo em outro e usar tipos de contas diferentes para se autenticar em cada computador, poderá experimentar um comportamento diferente. Por exemplo, suponha que você desenvolva seu aplicativo em um computador Windows XP Pro usando o modo de autenticação SSPI Negotiated. Se você usar uma conta de usuário local para se autenticar, o protocolo NTLM será usado. Depois que o aplicativo for desenvolvido, você implantará o serviço em um computador Windows Server 2003, em que ele é executado em uma conta de domínio. Neste ponto, o cliente não poderá autenticar o serviço porque ele usará o Kerberos e um controlador de domínio.

Confira também