2010-03-08 5 views
2

J'utilise un service WCF pour exposer certaines fonctions de gestion Active Directory à notre service d'assistance sans leur donner l'appartenance au groupe nécessaire pour manipuler directement AD. Ajout d'utilisateurs et suppression d'utilisateurs des groupes travaille comme un champion avec les utilisateurs existants, mais chaque fois que je crée un nouvel utilisateur, il rejette ce code amusant:L'ajout d'un utilisateur au groupe de sécurité AD échoue après la création de l'utilisateur

The server is unwilling to process the request. (Exception from HRESULT: 0x80072035) 

Le code que j'utilise pour ajouter l'utilisateur au groupe est

public bool AddGroupToUser(string userDn, string groupDn) 
    { 
     try 
     { 
      DirectoryEntry groupEntry = LdapTools.GetDirectoryEntry(groupDn); 
      groupEntry.Properties["member"].Add(userDn); 
      groupEntry.CommitChanges(); 
      groupEntry.Close(); 
      return true; 
     } 
     catch (DirectoryServicesCOMException) 
     { 
      return false; 
     } 
    } 

Tout ce que j'ai lu sur le sujet est assez vague et je ne peux pas sembler trouver pourquoi l'exception est déclenchée. Des idées?

MISE À JOUR

Voici le code que j'utilise pour créer l'utilisateur dans AD:

 try 
     { 
      DirectoryEntry container = GetDirectoryEntry(storageOu); 
      DirectoryEntry newUser = container.Children.Add("CN=" + employee.FullName, "user"); 
      newUser.Properties["sAMAccountName"].Value = employee.Username; 
      newUser.Properties["displayName"].Value = employee.FullName; 
      newUser.Properties["givenName"].Value = employee.FirstName; 
      newUser.Properties["sn"].Value = employee.LastName; 
      newUser.Properties["department"].Value = departmentName; 
      newUser.Properties["userPrincipalName"].Value = employee.Username + "@APEX.Local"; 
      newUser.CommitChanges(); 

      newUser.Invoke("SetPassword", new object[] { employee.Password }); 
      newUser.CommitChanges(); 

      AdsUserFlags userSettings = AdsUserFlags.NormalAccount; 
      newUser.Properties["userAccountControl"].Value = userSettings; 
      newUser.CommitChanges(); 

      ldapPath = newUser.Path; 

      newUser.Close(); 
      container.Close(); 
     } 
     catch (DirectoryServicesCOMException e) 
     { 
      // Something went wrong... what??? 
     } 
     catch (Exception e) 
     { 
      // Something else went wrong 
     } 

Le nouvel utilisateur peut se connecter, et peut être manipulé à l'aide des outils standard MS.

Répondre

2

Apparemment, à moins que je ne manque une étape importante ici, le problème est le temps. Lorsque vous forcez le système à s'endormir pendant 8 secondes avant d'essayer d'ajouter des groupes au nouvel utilisateur, le processus fonctionne. Si je le fais plus tôt que la marque de 8 secondes, il échoue.

Je marque cette réponse comme correcte à moins que n'importe qui peut me fournir une meilleure solution.

+0

Je ne pense pas que les primitives DirectoryEntry sont garanties d'utiliser la même liaison AD en interne, il est donc tout à fait possible de manipuler le groupe sur un contrôleur de domaine différent de celui auquel vous avez ajouté l'utilisateur (AD utilise un modèle de réplication multimaître). Le temps nécessaire à la réplication pour terminer dépend du nombre de contrôleurs de domaine, le paramètre qui détermine le délai d'attente avant de notifier les homologues d'un changement et le volume des transactions AD. Dans un grand domaine, j'ai vu AD prendre plus de 5 minutes pour répliquer pleinement un SPN, alors faites attention avec 8 secondes. –

+0

J'ai écrit un wrapper autour de DirectoryEntry visant à résoudre le problème de ne pas savoir à quel contrôleur de domaine je me connecte. Je me connecte au même DC chaque fois maintenant et il ne reconnaît toujours pas le DirectoryEntry sur les appels suivants avant que la période de 8 secondes ne soit passée. Heureusement, pour l'instant au moins, je n'ai qu'à m'inquiéter de deux DC. Le ciel m'aide si nous commençons à ajouter un DC par emplacement. Savez-vous d'un moyen de savoir quand le SPN a été entièrement répliqué? – thaBadDawg

1

Essayez:

public bool AddUserToGroup(string userName, string groupName) 

     { 

      bool done = false; 

      GroupPrincipal group = GroupPrincipal.FindByIdentity(context, groupName); 

      if (group == null) 

      { 

       group = new GroupPrincipal(context, groupName); 

      } 

      UserPrincipal user = UserPrincipal.FindByIdentity(context, userName); 

      if (user != null & group != null) 

      { 

       group.Members.Add(user); 

       group.Save(); 

       done = (user.IsMemberOf(group)); 

      } 

      return done; 

     } 

Référence:
http://www.c-sharpcorner.com/UploadFile/dhananjaycoder/activedirectoryoperations11132009113015AM/activedirectoryoperations.aspx

+0

bien sûr, cela ne fonctionne que sur .NET 3.5 et plus. –

0

Comme mentionné dans here, pouvez-vous nous dire que vous définissez le mot de passe des utilisateurs nouvellement créés? Dans la référence, il est dit que vous devez définir SetPassword de l'utilisateur avant de faire quoi que ce soit avec.

+0

Vous pouvez également vérifier le soluiton accepté dans http://www.experts-exchange.com/Programming/Misc/Q_21962620.html –

+0

Vérifiez la mise à jour du code que j'ai ajouté à la question, j'ai ajouté mon code de création d'utilisateur à elle. – thaBadDawg

+0

J'utilise le même code sur mon entreprise, sauf que la propriété userAccountControl de mon utilisateur a également la valeur "Le mot de passe n'expire pas". (ActiveDs.ADS_USER_FLAG.ADS_UF_DONT_EXPIRE_PASSWD) Pouvez-vous essayer de définir cette valeur aussi? –

0

Un problème de temps peut se produire à partir d'un problème de réplication Active Directory. Une fois, j'ai donné un produit à mon client qui crée un utilisateur sur Active Directory, qui contient plus de 10.000 enregistrements, avec les informations données sur un formulaire SharePoint, puis le programme ajoute l'utilisateur à un groupe SharePoint. Le problème était, SharePoint renvoie une erreur sur l'utilisateur nouvellement créé, il dit que l'utilisateur n'existe pas dans AD. Par conséquent, un des ingénieurs système nous a parlé de l'opération de réplication sur Active Directory qui pourrait être la source du problème et c'était vrai.

Pour la solution, le programme essaie de faire le travail pendant 10 fois avec 1 seconde de sommeil. Aucun problème n'est survenu jusqu'à présent. Donc, comme une solution, je vous suggère de vérifier l'AD pour l'existence de la méthode de réplication. P.S: Lorsque j'ai posé des questions aux ingénieurs système de mes clients à propos de l'opération de réplication, ils ont tous rejeté l'existence de l'opération de réplication AD et m'ont dit que le programme avait un problème. Ils m'ont cru quand nous avons créé un nouvel utilisateur dans AD à partir d'un ordinateur, nous ne pouvions pas voir l'utilisateur pendant 5 secondes sur un autre ordinateur.