2010-08-26 15 views
15

Sto tentando di utilizzare la libreria .NET System.DirectoryServices.AccountManagement per ottenere UserPrincipal per un particolare utente di Active Directory.UserPrincipal.FindByIdentity Autorizzazioni

Ho il seguente codice:

PrincipalContext context = new PrincipalContext(ContextType.Domain, "DomainName"); 
userPrincipal = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username); 

Questo codice viene eseguito come utente di dominio valido, ma quando eseguo io ottenere la seguente eccezione:

System.DirectoryServices. DirectoryServicesCOMException (0x8007052E): errore di accesso: nome utente sconosciuto o password errata.

La cosa interessante è che posso fare la seguente chiamata, utilizzando lo stesso contesto, senza un problema:

context.ValidateCredentials(username, password, ContextOptions.Negotiate) 

idee?

+0

Controllare questa risposta: http://stackoverflow.com/questions/1863801/findbyidentity-failing-with-pricipaloperationexception-in-asp-net-webapp/3515280#3515280 –

risposta

12

È necessario utilizzare il costruttore PrincipalContext che accetta nome utente e password.

Il motivo per cui Validate funziona è perché utilizza le credenziali fornite per collegarsi alla directory.

+0

questo non ha molto senso per me. Stai dicendo che la chiamata ValidateCredentials utilizza le credenziali di identità correnti, ma la chiamata UserPrincipal.FindByIdentity, che accetta il contesto in questione, non lo fa? In questo caso, come faccio a utilizzare l'identità corrente (come in, l'identità del thread) per effettuare la chiamata? Non ho un nome utente o una password da passare, in quanto si tratta di un'applicazione in esecuzione come impostazione dell'account di servizio al momento dell'installazione. Non riesco a memorizzare queste credenziali ovunque. – RMD

+0

Penso che tu abbia frainteso, ValidateCredentials usa le credenziali fornite nella lista dei parametri per ValidateCredentials - il Contesto che hai definito non ha credenziali associate ad esso oltre a quelle del thread corrente. Sospetto che i tuoi problemi siano nella configurazione/distribuzione del server. Assicurarsi che l'account che esegue il servizio sia stato delegato all'interno del dominio. – Nate

+0

Sì, ho frainteso. L'utente del thread corrente è definitivamente un utente di dominio valido. Quando dici "delegato all'interno del dominio", cosa intendi esattamente? – RMD

3

Sembra che tu disponga di credenziali di rete memorizzate. In Windows, è possibile specificare di utilizzare credenziali di rete diverse quando si tenta di raggiungere una risorsa di rete. Posso riprodurre esattamente lo stesso problema che stai vedendo impostando una rete errata.

Supponendo che il dominio sia chiamato yourdomain.com, è possibile indicare a Windows di utilizzare sempre un nome utente e una password specifici ogni volta che comunica con qualsiasi computer con suffisso yourdomain.com.

=== === di Windows 7/2008

  1. lanciare il "Crendentail Manager".
  2. Nella sezione delle credenziali di Windows, fare clic su Add a Windows credentials
  3. In indirizzo di rete, mettere in *.yourdomain.com
  4. nome utente e password, inserire un nome utente sbagliato o una password sbagliata

=== Windows XP/2000/2003 ===

  1. Fare clic su Start e su Esegui
  2. Digitare control keymgr.dll
  3. clic sul pulsante Aggiungi su "nomi utente e password" dialogo
  4. Nella casella di testo Server, messi in *.yourdomain.com
  5. nome utente e password, inserire il nome utente sbagliato o una password sbagliata

Se questo è davvero il problema che stai affrontando, la soluzione facile è quella di rimuovere le password memorizzate.

Perché context.ValidateCredentials (nome utente, password, ContextOptions.Negotiate) funzionano?È semplicemente perché stai inizializzando un'altra autenticazione Kerberos/NTLM poiché fornisci di nuovo uername e password. Sotto il cofano, se viene scelto Kerberos, invierà al controller di dominio il nome utente e la password forniti e si scambierà un ticket TGT Kerberos. Quindi, la macchina ottiene un ticket di servizio sul server LDAP utilizzando questo ticket TGT. Quindi, la macchina invierà questo ticket di servizio al server LDAP. Si noti che questo ticket di servizio non verrà mantenuto nella sessione di accesso corrente.

Perché UserPrincipal.FindByIdentity non funziona? Se non si dispone di alcuna password memorizzata, normalmente dovrebbe funzionare perché Windows utilizzerà semplicemente il ticket TGT dell'utente di accesso corrente per scambiarsi il ticket del servizio server LDAP. Non è richiesto il processo di convalida di nome utente/password. Tuttavia, se la password del nome utente è errata, Windows potrebbe non utilizzare il ticket TGT dell'utente di accesso corrente. Invece, dovrebbe ottenere un nuovo ticket TGT usando la password di rete memorizzata. Questo è il motivo che state vedendo System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password.

+0

Interessante. Questo codice è in esecuzione dal contesto di un'applicazione ASP.NET, quindi non penserei che le password memorizzate farebbero la differenza. Controllerò per vedere se hai ragione. – RMD

+0

@RMD Ah, hai perso questa informazione. Stai usando l'autenticazione di Windows? O stai semplicemente usando l'account di servizio locale per accedere all'AD? –

+0

Come ho detto nel mio post originale: "Questo codice è in esecuzione come utente di dominio valido". – RMD