2010-03-02 14 views
12

Ho un'applicazione MVC che deve effettuare il login e verificare un utente contro Active Directory. Sto usando il metodo PrincipalContext.ValidateCredentials ma ottengo sempre un'autenticazione di false.PrincipalContext.ValidateCredentials restituisce sempre FALSE

La connessione al server va bene. Il problema sembra verificarsi nello ValidateCredentials.

Ecco il mio codice:

public static bool IsAuthenticated(string domain, string username, string pwd) { 
    bool IsAuthenticated = false; 

    try { 
     PrincipalContext insPrincipalContext = 
      new PrincipalContext(ContextType.Domain, domain, "DC=c1w,DC=com"); 

     username = "c1w\\" + username; 

     IsAuthenticated = insPrincipalContext.ValidateCredentials(username, pwd); 
    } 
    catch (Exception ex) 
    { 
     // Rethrow this exception 
     ExceptionPolicy.HandleException(ex, "Exception Policy"); 
    } 

    return IsAuthenticated; 
} 

Chiunque sa perché questo sarebbe successo?

risposta

7

Non vedo dove si inizializza la variabile "pwd" Forse dovresti usare ContextOption in questo metodo per specificare esattamente il comportamento richiesto. Ci scusiamo per la risposta troppo ampia ma non ci sono molti dettagli nella tua domanda

+0

Modifica la domanda per includere l'intero metodo. Proverà il suggerimento di ContextOption. Grazie. –

+5

B-Rain, Il riferimento ContextOption mi ha indirizzato nella giusta direzione. Terminato utilizzando ContextOptions.Negotiate sulla mia chiamata ad AD e ContextOptions.SimpleBind sulle credenziali di convalida. Simple Bind funzionerà per me dal momento che il sito sarà protetto SSL. Grazie per il vostro aiuto. –

+0

Ho svalutato sia la domanda che la risposta perché questo mi ha aiutato anche nella mia situazione. Nel mio caso, la mia macchina di sviluppo (dove l'accesso funziona senza specificare il contesto) si trova nella zona protetta della rete, ma il server Web (dove l'accesso non funziona senza specificare il contesto) si trova nella DMZ. Ho usato la stessa configurazione di @Billy Logan - Negozia sulla chiamata ad AD e SimpleBind sulla chiamata valida. – arootbeer

1

Sembra che tu stia convalidando l'utente con il formato dominio \ nome utente. Si potrebbe voler analizzare il nome del dominio da userName e l'utente ValidateCredential.

12

Ecco come funziona ValidateCredentials(string, string): Innanzitutto, prova ad autenticare con le opzioni di contesto Negotiate, e Sealing. Se ciò non riesce, riprova con SimpleBind e SecureSocketLayer.

Il problema è che il formato NT4 (AKA "legacy", AKA "nome di livello inferiore") (DOMAIN\UserName, o più correttamente, NetBiosName\SamAccountName) non funziona con Negotiate. Ma funziona con SimpleBind.

Quindi, ciò che probabilmente accade quando si chiama il metodo ValidateCredentials() a 2 parametri, è che per prima cosa non riesce a utilizzare Negotiate perché non gli piace il formato NT4 e quindi fallisce nuovamente quando si utilizza il binding semplice.

Durante i miei test, ho scoperto che il motivo per cui non funziona, anche dopo aver ricominciato a utilizzare il binding semplice, è che non utilizza solo SimpleBind. Sta usando SimpleBind più SecureSocketLayer. Ciò significa che non funzionerà correttamente se il server di Active Directory non è impostato correttamente per utilizzare SSL (uno scenario comune per ambienti di test).

Come è stato menzionato in uno dei commenti, MAI, MAI, non si desidera MAI utilizzare SimpleBind da solo (senza SecureSocketLayer), altrimenti le password vengono inviate sulla rete in testo normale.

In natura, ho visto che alcuni sistemi di Active Directory non consentono affatto l'uso di collegamenti semplici, quindi è necessario farlo funzionare con Negotiate.

ho trovato 2 modi per affrontare questo problema:

1) Se tutto sta accadendo sullo stesso dominio, si dovrebbe essere in grado di chiamare ValidateCredentials con il solo nome utente (account SAM nome), lasciando fuori la parte "DOMINIO \". Quindi, funzionerà correttamente la prima volta con Negotiate.

2) Se la parte del dominio è importante perché potrebbero esserci più domini coinvolti (ad esempio Domain1\UserA e Domain2\UserA sono persone diverse), diventa un po 'più complicato. In questo caso, ho finito per tradurre il nome NT4 (DOMINIO \ Utente) in formato "nome principale utente" (ad esempio [email protected]). Ci sono un paio di modi diversi per farlo.Il modo più semplice è probabilmente utilizzare il sovraccarico a 3 parametri di UserPrincipal.FindByIdentity() e quindi acquisire il valore della proprietà UserPrincipalName sul risultato. Un altro modo sarebbe utilizzare un DirectorySearcher e una query LDAP://domain per la proprietà userPrincipalName dell'utente con il valore sAMAccountName corrispondente. Nota: questa soluzione funzionerà solo se tutti i domini coinvolti si trovano nella stessa foresta.

Problemi correlati