2010-08-26 21 views
15

Próbuję użyć biblioteki .NET System.DirectoryServices.AccountManagement, aby uzyskać UserPrincipal dla określonego użytkownika usługi Active Directory.UserPrincipal.FindByIdentity Uprawnienia

Mam następujący kod:

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

Ten kod jest uruchomiony jako ważnego użytkownika domeny, ale kiedy go wykonać otrzymuję następujący wyjątek:

System.DirectoryServices. DirectoryServicesCOMException (0x8007052E): Błąd logowania: nieznana nazwa użytkownika lub nieprawidłowe hasło.

Co ciekawe jest to, że mogę zrobić następującą rozmowę, używając tego samego kontekstu, bez problemu:

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

Pomysły?

+0

Zaznacz tę odpowiedź: http://stackoverflow.com/questions/1863801/findbyidentity-failing-with-pricipaloperationexception-in-asp-net-webapp/3515280#3515280 –

Odpowiedz

12

Należy użyć konstruktora PrincipalContext, który pobiera nazwę użytkownika i hasło.

Powodem, dla którego funkcja sprawdzania poprawności działa, jest fakt, że wykorzystuje ona podane poświadczenia do powiązania z katalogiem.

+0

To nie robi ma dla mnie wiele sensu. Mówisz, że wywołanie ValidateCredentials używa bieżących poświadczeń tożsamości, ale wywołanie UserPrincipal.FindByIdentity, które akceptuje kontekst, którego dotyczy pytanie, nie? Jeśli tak, to w jaki sposób sprawić, by wywołanie odbywało się przy użyciu bieżącej tożsamości (jak w tożsamości wątku)? Nie mam nazwy użytkownika ani hasła do przekazania, ponieważ jest to aplikacja działająca jako konfiguracja konta usługi w czasie instalacji. Nie mogę przechowywać tych poświadczeń w dowolnym miejscu. – RMD

+0

Myślę, że źle zrozumiałeś, ValidateCredentials używa poświadczeń podanych na liście parametrów dla ValidateCredentials - Kontekst, który zdefiniowałeś, nie ma powiązanych z nim poświadczeń poza tymi z bieżącego wątku. Podejrzewam, że twoje problemy dotyczą konfiguracji/wdrożenia serwera. Upewnij się, że konto, na którym działa usługa, zostało przekazane do domeny. – Nate

+0

Tak, źle mnie zrozumiałem. Użytkownik bieżącego wątku jest definitywnie prawidłowym użytkownikiem domeny. Kiedy mówisz "delegowany do domeny", co masz na myśli? – RMD

3

Wygląda na to, że masz zapisane poświadczenia sieciowe. W systemie Windows można określić użycie różnych poświadczeń sieciowych podczas próby uzyskania dostępu do zasobów sieciowych. Mogę odtworzyć dokładnie ten sam problem, co widzisz, konfigurując nieprawidłowe poświadczenia sieciowe.

Zakładając, że twoja domena nazywa się yourdomain.com, możesz nakazać systemowi Windows, aby zawsze używała określonej nazwy użytkownika i hasła, ilekroć rozmawia z każdym komputerem z wystarczającą ilością domeny twojadomena.com.

=== systemu Windows 7/2008 ===

  1. Uruchom "Crendentail Manager".
  2. W sekcji poświadczenia systemu Windows, kliknij Add a Windows credentials
  3. w adresie sieci, umieścić w *.yourdomain.com
  4. W nazwy użytkownika i hasła, umieścić w niewłaściwej nazwy użytkownika lub nieprawidłowe hasło

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

  1. Kliknij start i Uruchom
  2. Wpisz control keymgr.dll
  3. Kliknij przycisk Add na „Przechowywane nazwy użytkowników i hasła” dialogowych
  4. W polu tekstowym Server, umieszczone w *.yourdomain.com
  5. W nazwy użytkownika i hasła, umieścić w niewłaściwej nazwy użytkownika lub nieprawidłowe hasło

Jeśli jest to naprawdę problem, przed którym stoisz, łatwym rozwiązaniem jest usunięcie zapisanych haseł.

Dlaczego metoda context.ValidateCredentials (nazwa użytkownika, hasło, ContextOptions.Negotiate) działa?Dzieje się tak dlatego, że inicjujesz kolejne uwierzytelnianie Kerberos/NTLM, ponieważ ponownie dajesz uername i. Pod maską, jeśli wybrano Kerberos, wysłał kontroler domeny podaną nazwę użytkownika i hasło oraz wymieniłby się biletem TGT Kerberos. Następnie Twój komputer otrzymuje bilet usługi na serwerze LDAP przy użyciu tego biletu TGT. Następnie urządzenie wyśle ​​ten bilet usługi do serwera LDAP. Należy zauważyć, że ten bilet usługi nie zostanie zachowany w bieżącej sesji logowania.

Dlaczego UserPrincipal.FindByIdentity nie działa? Jeśli nie masz zapisanego hasła, normalnie powinno działać, ponieważ system Windows po prostu użyje bieżącego biletu TGT użytkownika do wymiany na bilet usługi serwera LDAP. Nie jest zaangażowany proces sprawdzania nazwy użytkownika/hasła. Jeśli jednak masz złe hasło do nazwy użytkownika, system Windows pomyśli, że nie powinien używać aktualnego biletu TGT dla użytkownika. Zamiast tego powinien otrzymać nowy bilet TGT za pomocą zapisanego hasła sieciowego. To jest powód widzisz System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password.

+0

Interesujące. Ten kod jest uruchamiany z kontekstu aplikacji ASP.NET, więc nie sądzę, by przechowywane hasła miały znaczenie. Sprawdzę, czy masz rację. – RMD

+0

@RMD Ah, tęskniłeś za tą informacją. Czy używasz uwierzytelniania systemu Windows? A może po prostu używasz lokalnego konta usługi, aby uzyskać dostęp do AD? –

+0

Tak jak napisałem w moim oryginalnym wpisie: "Ten kod działa jako ważny użytkownik domeny". – RMD