Laden...

WCF: Authentifizierung um auf AD zuzugreifen

Erstellt von msycho vor 12 Jahren Letzter Beitrag vor 12 Jahren 2.926 Views
M
msycho Themenstarter:in
234 Beiträge seit 2007
vor 12 Jahren
WCF: Authentifizierung um auf AD zuzugreifen

Hi!

Ich habe hier ein WCF-Service, der ueber den DirectoryServices-Namespace auf die Active Directory zugreift.
Dem instanziierten DirectoryEntry Objekt kann ich ueber die Eigenschaften Username und Password den Benutzer angeben ueber den der Zugriff stattfinden soll.
Funktioniert alles soweit problemlos bis zu dem Zeitpunkt an dem ich den Service auf den IIS deploy.
Der Service laeuft unter einem bestimmten AppPool, der wiederrum unter einem bestimmten Service Account laeuft. Dieser Service Account hat keine Rechte auf die AD zuzugreifen. Soll er auch nicht; ich setze den zu verwenden Benutzer ja wie oben beschrieben im Code.
Doch genau hier ist das Problem. Der Benutzer unter dem der AppPool laeuft scheint Prioritaet zu haben. Denn ich kann mich anscheinend nicht erfolgreich authentifizieren ggue. der AD. Die Message lautet > Fehlermeldung:

unknown user name or bad password .
Sobald ich jetzt den Benutzer unter dem der AppPool laeuft, aendere auf den selben Benutzer, den ich auch im Code verwende, funktioniert der Zugriff einwandfrei.
Wie kann ich es realisieren, dass der Benutzer, den ich im Code definiere benutzt wird um sich ggue. der AD zu authentifizieren?

Danke und VG!

G
538 Beiträge seit 2008
vor 12 Jahren

Ich würde Vermuten, dass die Fehlermeldung genau zutrifft (nämlich falsches PW/Username)

Wie ermittelst du denn Passwort und Benutzername?

//Um die Frage genauer zu gestalten:
Nutzt du Kerberos/NTLM, Digest, Basic?
Ist das Hardcodiert?

Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)

M
msycho Themenstarter:in
234 Beiträge seit 2007
vor 12 Jahren

Der Benutzer und das Passwort sind definitiv nicht falsch.
Wenn ich diesen Benutzer im AppPool verwende, funktioniert es; wenn er unter der ApplicationPoolIdentity rennt und ich (wie gewollt) im Code ueber DirectoryEntry.Username den Benutzer definiere mit dem ich auf die AD zugreife, kommt die Eingangs erwaehnte Fehlermeldung.

Was muss ich beachten, damit die im Code verwendeten Credentials Prioritaet haben?

16.807 Beiträge seit 2008
vor 12 Jahren

Das funktioniert lokal vermutlich, weil hier Dein User verwendet wird und der über die nötigen Rechte verfügt. Führst Du lokal hier ebenfalls einen AppPool-User aus, dann wirst Du feststellen, dass es lokal auch nicht funktioniert > (Theorie)

Man sollte aber mittlerweile lieber System.DirectoryServices.AccountManagement Namespace nutzen, um mit dem AD zu agieren.

Via PrincipalContext Constructor (ContextType, String, String, String) kannst Du auch definitiv eine korrekte Authentifizierung für den aktuelle Kontext ausführen.
Hierbei ist auch die Impersonation egal.

Vielleicht zeigst Du einfach mal ein wenig Code.
Dass das AD Dich anlügt und Dir umsonst sagt, dass das Passwort falsch ist - das können wir ausschließen.

M
msycho Themenstarter:in
234 Beiträge seit 2007
vor 12 Jahren

Deine Vermutung ist vollkommen angebracht und auch richtig - und plausibel.

Hier wie gewuenscht ein vereinfachter Schnippsel:

string path = "LDAP://DC=test,DC=company,DC=org";
//relevante Stelle!
DirectoryEntry entry = new DirectoryEntry(path, 
"svcaccount", "svcaccountpassword");

//wir legen den user an und setzen die Props
DirectoryEntry user = entry.Children.Add("CN=Test User", "user");
user.Properties["sAMAccountName"].Add("testuser");
user.Properties["sn"].Add("User");
user.Properties["givenName"].Add("Test");
user.Properties["description"].Add("Test account added with code.");
user.CommitChanges();

//wir legen das Passwort fest
user.Invoke("SetPassword", new object[] {"mypassword1"} );

//der Acc ist enabled
user.Properties["userAccountControl"].Value = 0x200; 
user.CommitChanges();

16.807 Beiträge seit 2008
vor 12 Jahren

Nutz mal den von mir genannten Namespace bzw die Methode. Die vereinfacht vieles und sorgt auch für den richtigen Kontext.
Das sind alles Properties, für die man DirectoryEntry nicht zwingend benötigt.

Ach noch als Hinweis: es wird ausdrücklich bei Web-Anwendungen und Web-Services lieber immer einen eigenen AppPool für die jeweilige Anwendung anzulegen.
Warum Du den User im Code setzen willst weiß ich nicht. Für mein Verständnis und auch auf vieler Empfehlungen hin, sollte man lieber dem AppPool den nötigen User geben.

Vorteile*potentiell weniger Wartungsaufwand *Authentifizierungen im Code sind anfälliger als im AppPool

M
msycho Themenstarter:in
234 Beiträge seit 2007
vor 12 Jahren

Abgesehen davon, dass damit die Authentizierung auch nicht funktioniert, hilft mir der Namespace nur bedingt. Der Namespace bietet mir nur begrenzt die Moeglichkeiten, die ich brauche, sodass ich UserPrincipal in DirectoryEntry wandeln muss.

Der eigene AppPool ist da und der laeuft jetzt auch unter dem besagten Benutzer. Es haette aus Wartungsgruenden in meinem Fall aber auch Vorteile gehabt, den Benutzer ueber die Config zu pflegen, aber das ist eine andere Geschichte.

Ich danke Euch!

16.807 Beiträge seit 2008
vor 12 Jahren

Welche Funktionen bietet Dir denn der genannte Namespace nicht?

User Erstellen funktionier einfach über


var myNewUser = new UserPrincipal( myContext, mySamAccountName, myPassword, isEnabled );
myNewUser.Save()

Und für's Password gibt's dann die ChangePassword() Methode.

Wenn auch über die Variante nicht der korrekte Kontext aufgebaut werden kann, stimmt etwas bei Dir an andere Stelle nicht.
Ich bin sehr fleißig im Nutzen von AD Funktionen und mir kam bisher kein Fehlverhalten unter die Nase.

M
msycho Themenstarter:in
234 Beiträge seit 2007
vor 12 Jahren

So muessen zum Beispiel diverse variablen Properties gesetzt werden, die so ueber den von Dir genannten Namespace nicht ansprechbar sind.

Btw, fuer die Nachwelt vielleicht etwas Lektuere zum Einlesen:
Create the New User Object
Managing Directory Security Principals in the .NET Framework 3.5

Ich traue der Testing-Stage langsam auch nicht mehr. Auf andere Umgebungen portiert, funktioniert es einwandfrei. Offensichtlich stimmt da etwas ganz anderes nicht. 🙄

16.807 Beiträge seit 2008
vor 12 Jahren

Du kannst jede Art von Property auch mit dem UserPrincipal auslesen. Hierzu gibt es ExtensionSet() und ExtensionGet().

Mittels Class-Extension ist das ganze dann auch sehr einfach zu implementieren.
Siehe auch How to use AD Attributes not represented in UserPrincipal, GroupPrincipal and ComputerPrincipal

Es gibt absolut keinen Grund mehr die veraltete Variante zu nutzen, außer man muss aktiv auf den Query Einfluss haben; zB aufgrund von Forest-/Trust-Einstellungen.

Sobald Du Custom Properties hast bietet es sich sowieso an, eigene Principals zu definieren, so wie in dem Beispiel auf der verlinkten CodeProject-Seite.