问题
I'd like find the groups list where a user is member. I tried several solution from http://www.codeproject.com/KB/system/everythingInAD.aspx but no result.
This code give me a "true", means LDAP is running :
public static bool Exists(string objectPath)
{
bool found = false;
if (DirectoryEntry.Exists("LDAP://" + objectPath))
found = true;
return found;
}
Thanks,
Update 1:
public ArrayList Groups(string userDn, bool recursive)
{
ArrayList groupMemberships = new ArrayList();
return AttributeValuesMultiString("memberOf", "LDAP-Server",
groupMemberships, recursive);
}
public ArrayList AttributeValuesMultiString(string attributeName,
string objectDn, ArrayList valuesCollection, bool recursive)
{
DirectoryEntry ent = new DirectoryEntry(objectDn);
PropertyValueCollection ValueCollection = ent.Properties[attributeName];
IEnumerator en = ValueCollection.GetEnumerator();
while (en.MoveNext())
{
if (en.Current != null)
{
if (!valuesCollection.Contains(en.Current.ToString()))
{
valuesCollection.Add(en.Current.ToString());
if (recursive)
{
AttributeValuesMultiString(attributeName, "LDAP://" +
en.Current.ToString(), valuesCollection, true);
}
}
}
}
ent.Close();
ent.Dispose();
return valuesCollection;
}
I have an exception on :
PropertyValueCollection ValueCollection = ent.Properties[attributeName];
"COMException was unhandled"
回答1:
In .NET 4 you can do this very easily with the new UserPrincipal class in the following way:
using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
{
UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "your_login");
foreach (var group in user.GetGroups())
{
Console.WriteLine(group.Name);
}
}
You have to add a reference to System.DirectoryServices.AccountManagement
to bring in the required types.
回答2:
I found the solution on stackoverflow. The connectionString format is like this :
LDAP://domain.subdomain.com:389/DC=domain,DC=subdomain,DC=com
The Code :
public IList<string> GetGroupsByUser(string ldapConnectionString, string username)
{
IList<string> groupList = new List<string>();
var identity = WindowsIdentity.GetCurrent().User;
var allDomains = Forest.GetCurrentForest().Domains.Cast<Domain>();
var allSearcher = allDomains.Select(domain =>
{
var searcher = new DirectorySearcher(new DirectoryEntry(ldapConnectionString));
// Apply some filter to focus on only some specfic objects
searcher.Filter = String.Format("(&(&(objectCategory=person)(objectClass=user)(name=*{0}*)))", username);
return searcher;
});
var directoryEntriesFound = allSearcher
.SelectMany(searcher => searcher.FindAll()
.Cast<SearchResult>()
.Select(result => result.GetDirectoryEntry()));
var memberOf = directoryEntriesFound.Select(entry =>
{
using (entry)
{
return new
{
Name = entry.Name,
GroupName = ((object[])entry.Properties["MemberOf"].Value).Select(obj => obj.ToString())
};
}
});
foreach (var item in memberOf)
foreach (var groupName in item.GroupName)
groupList.Add(groupName);
return groupList;
}
回答3:
Are you sure that above script is correct and works correctly? I don't think it will take nested group memberships into account, so I fear that you may not be getting the complete set of all groups to which a user belongs.
You see, a user could be a member of Group X, and Group X could in turn be a member of Group Y, so as a result the user would be a member of Group Y as well.
I think the script referenced above may not be able to expand and enumerate nested group memberships.
I would suggest looking into this angle as well, if you are interested in getting the full set of memberships to which the user belongs.
I believe there are some other issues pertaining to determining group membership as well. There is a good discussion here if you are interested in learning more:
http://www.activedirsec.org/t39703252/why-is-it-so-hard-to-enumerate-nested-group-memberships-in-a/
I wish it very easier, but it does not appear to be so :-(
回答4:
Use this code instead of your version. This will give you the list. The difference between this and the original one is the usage of DirectorySearcher.
public ArrayList AttributeValuesMultiString(string attributeName,
string objectDn, ArrayList valuesCollection, bool recursive)
{
using (DirectoryEntry ent = new DirectoryEntry(objectDn))
{
using (DirectorySearcher searcher = new DirectorySearcher(ent))
{
searcher.PropertiesToLoad.Add(attributeName);
var result = searcher.FindOne();
ResultPropertyValueCollection ValueCollection = result.Properties[attributeName];
IEnumerator en = ValueCollection.GetEnumerator();
while (en.MoveNext())
{
if (en.Current != null)
{
if (!valuesCollection.Contains(en.Current.ToString()))
{
valuesCollection.Add(en.Current.ToString());
if (recursive)
{
AttributeValuesMultiString(attributeName, "LDAP://" +
en.Current.ToString(), valuesCollection, true);
}
}
}
}
}
}
return valuesCollection;
}
来源:https://stackoverflow.com/questions/7305279/active-directory-get-groups-where-a-user-is-member