Condividi tramite


Eseguire il debug degli errori di autenticazione di Windows

Quando si usa l'autenticazione di Windows come meccanismo di sicurezza, l'interfaccia SSPI (Security Support Provider Interface) gestisce i processi di sicurezza. Quando si verificano errori di sicurezza a livello SSPI, vengono visualizzati da Windows Communication Foundation (WCF). Questo argomento fornisce un framework e un set di domande che consentono di diagnosticare gli errori.

Per una panoramica del protocollo Kerberos, vedere Kerberos Explained; per una panoramica di SSPI, vedere SSPI.

Per l'autenticazione di Windows, WCF utilizza solitamente il provider di supporto per la sicurezza Negotiate (SSP), che esegue l'autenticazione reciproca Kerberos tra il client e il servizio. Se il protocollo Kerberos non è disponibile, per impostazione predefinita WCF esegue il fallback a NT LAN Manager (NTLM). Tuttavia, è possibile configurare WCF in modo che usi solo il protocollo Kerberos e per generare un'eccezione se Kerberos non è disponibile. È anche possibile configurare WCF per l'uso di forme limitate del protocollo Kerberos.

Metodologia di debug

Il metodo di base è il seguente:

  1. Determinare se si usa l'autenticazione di Windows. Se si usa qualsiasi altro schema, questo argomento non si applica.

  2. Se si è certi di usare l'autenticazione di Windows, determinare se la configurazione WCF usa Kerberos direct o Negotiate.

  3. Dopo aver determinato se la configurazione usa il protocollo Kerberos o NTLM, è possibile comprendere i messaggi di errore nel contesto corretto.

Disponibilità del protocollo Kerberos e NTLM

Il provider di servizi condivisi Kerberos richiede che un controller di dominio funga da Centro distribuzione chiavi Kerberos (KDC). Il protocollo Kerberos è disponibile solo quando il client e il servizio usano identità di dominio. In altre combinazioni di account viene usato NTLM, come riepilogato nella tabella seguente.

Le intestazioni di tabella mostrano i possibili tipi di account utilizzati dal server. La colonna a sinistra mostra i possibili tipi di account usati dal client.

Utente locale Sistema locale Utente di dominio Computer di dominio
Utente locale NTLM NTLM NTLM NTLM
Sistema locale NTLM anonimo NTLM anonimo NTLM anonimo NTLM anonimo
Utente di dominio NTLM NTLM Kerberos Kerberos
Computer di dominio NTLM NTLM Kerberos Kerberos

In particolare, i quattro tipi di account includono:

  • Utente locale: profilo utente esclusivo per macchina. Ad esempio: MachineName\Administrator o MachineName\ProfileName.

  • Sistema locale: l'account predefinito SYSTEM su un computer che non è collegato a un dominio.

  • Utente di dominio: un account utente in un dominio di Windows. Ad esempio: DomainName\ProfileName.

  • Computer di dominio: un processo con identità macchina in esecuzione su una macchina connessa a un dominio Windows. Ad esempio: MachineName\Network Service.

Annotazioni

Le credenziali del servizio vengono acquisite quando viene chiamato il Open metodo della ServiceHost classe . Le credenziali client vengono lette ogni volta che il client invia un messaggio.

Problemi comuni di autenticazione di Windows

Questa sezione illustra alcuni problemi comuni di autenticazione di Windows e possibili rimedi.

Protocollo Kerberos

Problemi di SPN/UPN con il protocollo Kerberos

Quando si usa l'autenticazione di Windows e il protocollo Kerberos viene usato o negoziato da SSPI, l'URL usato dall'endpoint client deve includere il nome di dominio completo dell'host del servizio all'interno dell'URL del servizio. Ciò presuppone che l'account sotto il quale il servizio è in esecuzione abbia accesso alla chiave del nome dell'entità servizio (SPN) del computer (impostazione predefinita) creata quando il computer viene aggiunto all'Active Directory, operazione eseguita più comunemente eseguendo il servizio nell'account Servizio di rete. Se il servizio non ha accesso alla chiave SPN del computer, è necessario specificare il nome SPN o l'entità utente (UPN) corretto dell'account con cui il servizio è in esecuzione nell'identità dell'endpoint del client. Per altre informazioni sul funzionamento di WCF con SPN e UPN, vedere Identità e autenticazione del servizio.

Negli scenari di bilanciamento del carico, ad esempio web farm o giardini Web, una procedura comune consiste nel definire un account univoco per ogni applicazione, assegnare un nome SPN a tale account e assicurarsi che tutti i servizi dell'applicazione vengano eseguiti in tale account.

Per ottenere un nome SPN per l'account del servizio, è necessario essere un amministratore di dominio di Active Directory. Per altre informazioni, vedere Supplemento tecnico Kerberos per Windows.

Il protocollo Kerberos Direct richiede che il servizio venga eseguito con un account macchina di dominio

Ciò si verifica quando la ClientCredentialType proprietà è impostata su Windows e la NegotiateServiceCredential proprietà è impostata su false, come illustrato nel codice seguente.

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

Per risolvere il problemi, eseguire il servizio usando un account del computer di dominio, ad esempio servizio di rete, in un computer aggiunto a un dominio.

La delega richiede la negoziazione delle credenziali

Per usare il protocollo di autenticazione Kerberos con la delega, è necessario implementare il protocollo Kerberos con la negoziazione delle credenziali (talvolta denominata "multi-leg" o "multi-step" Kerberos). Se si implementa l'autenticazione Kerberos senza negoziazione delle credenziali (talvolta denominata "one-shot" o "single-leg" Kerberos), verrà generata un'eccezione.

Per implementare Kerberos con negoziazione delle credenziali, seguire questa procedura:

  1. Implementare la delega impostando AllowedImpersonationLevel su Delegation.

  2. Richiedi negoziazione SSPI:

    1. Se si usano associazioni standard, impostare la NegotiateServiceCredential proprietà su true.

    2. Se si usano associazioni personalizzate, impostare l'attributo AuthenticationMode dell'elemento Security su SspiNegotiated.

  3. Richiedere alla negoziazione SSPI di utilizzare Kerberos escludendo l'uso di NTLM.

    1. Eseguire questa operazione nel codice con l'istruzione seguente: ChannelFactory.Credentials.Windows.AllowNtlm = false

    2. In alternativa, è possibile eseguire questa operazione nel file di configurazione impostando l'attributo allowNtlm su false. Questo attributo è contenuto nelle <finestre>.

Protocollo NTLM

Negotiate SSP passa a NTLM, ma NTLM è disabilitato

La AllowNtlm proprietà è impostata su false, il che induce Windows Communication Foundation (WCF) a tentare di generare un'eccezione se viene utilizzato NTLM. L'impostazione di questa proprietà su false potrebbe non impedire l'invio delle credenziali NTLM attraverso la rete.

Di seguito viene illustrato come disabilitare il fallback a NTLM.

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

Errore di accesso NTLM

Le credenziali client non sono valide nel servizio. Verificare che il nome utente e la password siano impostati correttamente e corrispondano a un account noto al computer in cui è in esecuzione il servizio. NTLM usa le credenziali specificate per accedere al computer del servizio. Anche se le credenziali potrebbero essere valide nel computer in cui è in esecuzione il client, l'accesso avrà esito negativo se le credenziali non sono valide nel computer del servizio.

Si verifica l'accesso NTLM anonimo, ma gli accessi anonimi sono disabilitati per impostazione predefinita

Quando si crea un client, la AllowedImpersonationLevel proprietà è impostata su Anonymous, come illustrato nell'esempio seguente, ma per impostazione predefinita il server non consente accessi anonimi. Ciò si verifica perché il valore predefinito della AllowAnonymousLogons proprietà della WindowsServiceCredential classe è false.

Il codice client seguente tenta di abilitare gli accessi anonimi (si noti che la proprietà predefinita è 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

Il codice del servizio seguente modifica l'impostazione predefinita per abilitare gli accessi anonimi dal server.

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

Per ulteriori informazioni sull'impersonazione, vedere Delega e Impersonazione.

In alternativa, il client è in esecuzione come servizio Windows, usando l'account predefinito SYSTEM.

Altri problemi

Le credenziali client non sono impostate correttamente

L'autenticazione di Windows usa l'istanza WindowsClientCredential restituita dalla ClientCredentials proprietà della ClientBase<TChannel> classe , non dall'oggetto UserNamePasswordClientCredential. Di seguito è riportato un esempio errato.

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!

Di seguito viene illustrato l'esempio corretto.

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()

SSPI non è disponibile

I sistemi operativi seguenti non supportano l'autenticazione di Windows quando vengono usati come server: Windows XP Home Edition, Windows XP Media Center Edition e Windows Vista Home Edition.

Sviluppo e distribuzione con identità diverse

Se si sviluppa l'applicazione in un computer e si distribuisce in un altro e si usano tipi di account diversi per l'autenticazione in ogni computer, è possibile che si verifichi un comportamento diverso. Si supponga, ad esempio, di sviluppare l'applicazione in un computer Windows XP Pro usando la SSPI Negotiated modalità di autenticazione. Se si usa un account utente locale per l'autenticazione, verrà usato il protocollo NTLM. Una volta sviluppata l'applicazione, si distribuisce il servizio in un computer Windows Server 2003 in cui viene eseguito con un account di dominio. A questo punto, il client non sarà in grado di autenticare il servizio perché usa Kerberos e un controller di dominio.

Vedere anche