Tipps und Tricks rund um .NET und Visual Studio

Eigenschaften eines Benutzerkontos ändern
Kommentare

Dr. Holger Schwichtenberg (MVP) und FH-Prof. Manfred Steyer teilen in der Kolumne „.NETversum“ ihr Expertenwissen rund um .NET-Tools und WPF mit.

Seit .NET 3.5 kann ein Softwareentwickler viele Eigenschaften eines Benutzerskontos komfortabel über die Klassen des Namensraums System.DirectoryServices.AccountManagement (System.DirectoryServices.AccountManagement.dll) ändern.

Änderung der Eigenschaften eines Benutzerkontos

Listing 1 zeigt den Zugriff auf ein Active-Directory-Benutzerkonto und die Änderung von E-Mail-Adresse, Telefonnummer, Kennwort und Kennworteigenschaften.

 // Auf den Standort des Benutzerkontos zugreifen
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "E10", "OU=test,DC=IT-Visions,DC=local");

  // Benutzerobjekt holen
  Console.WriteLine("--- Benutzer holen: ");
  UserPrincipal up = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "HSchwichtenberg");
 
  // Werte auslesen
  Console.WriteLine(up.Name);
  Console.WriteLine(up.EmailAddress);
  Console.WriteLine(up.VoiceTelephoneNumber);

  // Werte verändern
  up.EmailAddress = "H.Schwichtenberg@IT-Visions.de";
  up.VoiceTelephoneNumber = "+49 201 649590-0";

  // Kennwort neu setzen
  up.SetPassword("Sehr+Geheim");
 
  // Kennworteigenschaften festlegen
 
  // Entweder nie ablaufendes, nicht änderbares Kennwort
  up.PasswordNeverExpires = true;
  up.UserCannotChangePassword = true;
 
  // oder Temporäres Kennwort
  up.ExpirePasswordNow(); // = "User must change password at next logon"
 
  // Änderungen speichern
  up.Save();

Allerdings wird man viele (genau genommen: die zahlenmäßig meisten) Eigenschaften eines Benutzerkontos vergeblich in dem UserPrincipal-Objekt suchen. Es fehlt zum Beispiel das Büro (Office), alle Adressangaben, die erweiterten Kommunikationsdaten und Einträge der Registerkarte „Organisation“. Der Zugriff auf alle Eigenschaften des „User“-Objekts im Active Directory bekommt man nur über ein System.DirectoryServices.DirectoryEntry-Objekt. Solch ein Objekt kann man über den LDAP-Pfad instanziieren.

 DirectoryEntry de = new DirectoryEntry("LDAP://cn=HSchwichtenberg,OU=test,DC=IT-Visions,DC=local");
  Console.WriteLine("Active Directory-Objekttyp: " + de2.SchemaClassName);

Danach kann man über die Properties-Eigenschaft auf die Verzeichnisattribute direkt zugreifen. Zu beachten ist, dass dabei die teilweise kuriosen LDAP-Namen zu verwenden sind, also z. B. das sehr kurze „l“ für die Stadt und das sehr lange „physicalDeliveryOfficeName“ für das Büro. Einige Verzeichnisattribute sind mehrwertig (d. h. sie können mehrere Werte besitzen). Ein Beispiel dafür ist otherTelephone. An dieser Stelle ist dann der Wert nicht mit Value = zu setzen, sondern durch Aufruf der Add()-Methode. Wenn ein Wert mit Add() hinzugefügt wird, den es schon gibt, ist das nicht schlimm. Der Wert ist danach nicht doppelt vorhanden.

Add() kann man auch bei einwertigen Attributen verwenden. Allerdings kann man auf diesem Weg einen bestehenden Wert nicht ändern. Nur ein Add() mit dem gleichen Wert, der schon im Verzeichnisattribut existiert, klappt. Ein Add() mit einem neuen Wert führt zum nichtssagenden Fehler „The server is unwilling to process the request.“ bei CommitChanges(). Leider steht nicht dabei, wo das Problem liegt.

Man muss natürlich aufpassen, dass man die richtigen Namen verwendet und sie auch korrekt schreibt. Leider kommt es erst beim Aufruf CommitChanges() zum Fehler, und die Fehlermeldung („The specified directory service attribute or value does not exist.“) sagt leider nichts darüber aus, welcher Verzeichnisattributname falsch ist (Listing 2).

// Registerkarte "General"
  de.Properties["physicalDeliveryOfficeName"].Value = "R0203";
  de.Properties["otherTelephone"].Add("0201 649590-0");
  de.Properties["otherTelephone"].Add("0201 649590-50");
 
  // Registerkarte "Organization"
  de.Properties["company"].Value = "www.IT-Visions.de";
  de.Properties["department"].Value = "Softwareentwicklung";
  de.Properties["title"].Value = "Technischer Leiter";
 
  // Registerkarte "Address"
  de.Properties["l"].Value = "Essen";
  de.Properties["st"].Value = "NRW";
  de.Properties["co"].Value = "Deutschland";
  de.Properties["streetAddress"].Value = "Fahrenberg 40b";
  de.Properties["postalCode"].Value = "45257";
  de.CommitChanges();

Wenn man schon ein UserPrincipal-Objekt in Händen hält, dann gibt es einen Abkürzungsweg zum DirectoryEntry-Objekt, denn die Klasse UserPrincipal kapselt die Klasse DirectoryEntry. Die Methode GetUnderlyingObject() liefert zu einem UserPrincipal-Objekt das zugehörige DirectoryEntry-Objekt. Am Ende kann man dann mit Save() aus der Klasse UserPrincipal auch die Änderungen am DirectoryEntry-Objekt im Active Directory persistieren (Listing 3).

// Auf den Standort des Benutzerkontos zugreifen
  PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "E10", "OU=test,DC=IT-Visions,DC=local");
 
  // Benutzerobjekt holen
  Console.WriteLine("--- Benutzer holen: ");
  UserPrincipal up = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "HSchwichtenberg");

  // Werte direkt im Benutzerobjekt verändern
  up.EmailAddress = "H.Schwichtenberg@IT-Visions.de";
  up.VoiceTelephoneNumber = "+49 201 649590-0";

  // Weitere Eigenschaften setzen über das zugrundeliegende ADSI-Objekt
  DirectoryEntry de = up.GetUnderlyingObject() as DirectoryEntry;
  Console.WriteLine("Active Directory-Objekttyp: " + de.SchemaClassName);

  // Registerkarte "General"
  de.Properties["physicalDeliveryOfficeName"].Value = "R0203";
  de.Properties["otherTelephone"].Add("0201 649590-0");
  de.Properties["otherTelephone"].Add("0201 649590-50");

  // usw. 

  // Änderungen speichern
  up.Save();
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -