我正在使用以下代码来获取我的域中组的成员:
Dim de As New DirectoryEntry("LDAP://" & GroupDN)
For Each user As String In CType(de.Properties("member"), IEnumerable)
GroupCollection.Add(Username, Username)
Next
Run Code Online (Sandbox Code Playgroud)
我的问题是,当GroupDN(组的可分辨名称)是" CN = Domain Users,CN = Users,DC = Mydomain,DC = local "时,For ... Each循环不执行,当我检查时手动使用属性语句,它的计数为零.这似乎适用于我的域中的每个其他组,但"域用户"组应该包含所有人,并且它似乎包含任何人.
我已经检查过,该组在我的Windows AD工具中正确列出了所有人.我有什么明显的遗漏吗?另外,有没有更好的方法来获得一个团体的所有成员?
Microsoft有一篇通用知识库文章(Q316748),描述了如何使用该DirectoryEntry对象对Active Directory进行身份验证.在他们的示例中,他们通过将域名和用户名连接到标准NetBIOS格式("domain\username")并将其作为参数传递给目录条目构造函数来生成用户名值:
string domainAndUsername = domain + @"\" + username;
DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);
Run Code Online (Sandbox Code Playgroud)
它最近引起了我们的注意,用户名的域名部分被完全忽略,在多个环境中我已经确认了这种行为.实际上正在使用用户名和密码,因为身份验证在无效时失败,但可以为域名和身份验证传递提供任意值.我一眼就认为这种格式适用于基于WinNT的目录访问,但LDAP的域部分被忽略.
谷歌检查显示许多LDAP示例将"域\用户名"值传递给DirectoryEntry对象,所以我要么在我的配置中弄乱了一些东西,或者很多人对KB文章感到困惑.任何人都可以确认这是预期的行为或建议一种方法来接受"域\用户名"值并与他们对Active Directory进行身份验证?
谢谢,
扩展UserPrincipal以利用其内置属性...当我们重载FindByIdentity()方法时遇到问题.
来自Microsoft的示例http://msdn.microsoft.com/en-us/library/bb384372%28VS.90%29.aspx(为简洁起见,不包括部分):
[DirectoryRdnPrefix("CN")]
[DirectoryObjectClass("inetOrgPerson")]
public class InetOrgPerson : UserPrincipal {
// Implement the overloaded search method FindByIdentity
public static new InetOrgPerson FindByIdentity(PrincipalContext context,
string identityValue) {
return (InetOrgPerson)FindByIdentityWithType(context,
typeof(InetOrgPerson),
identityValue);
}
// Implement the overloaded search method FindByIdentity
public static new InetOrgPerson FindByIdentity(PrincipalContext context,
IdentityType identityType,
string identityValue) {
return (InetOrgPerson)FindByIdentityWithType(context,
typeof(InetOrgPerson),
identityType,
identityValue);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我从MSDN示例中获取确切的代码并将其粘贴到我的应用程序中,它就不起作用.调用InetOrgPerson.FindByIdentity()返回null,如下:
if (null == InetOrgPerson.FindByIdentity(principalContext, UserName)) {
throw new Exception("bah");
}
Run Code Online (Sandbox Code Playgroud)
实际上,从内部InetOrgPerson.FindByIdentity()调用FindByIdentityWithType()返回null,如下: …
c# directoryservices active-directory account-management userprincipal
我用这个代码:
DirectoryEntry objEntry;
DirectorySearcher objSearchEntry;
SearchResultCollection objSearchResult;
string strFilter = "(&(objectCategory=User))";
objEntry = new DirectoryEntry(conOUPath, conUser, conPwd, AuthenticationTypes.Secure);
objEntry.RefreshCache();
objSearchEntry = new DirectorySearcher(objEntry);
objSearchEntry.Filter=strFilter;
objSearchEntry.SearchScope=SearchScope.Subtree;
objSearchEntry.CacheResults=false;
objSearchResult=objSearchEntry.FindAll();
Run Code Online (Sandbox Code Playgroud)
每次只返回1000个用户,但该OU中有3000个用户.
我怎样才能找到所有这些?
给定域用户的用户名和密码,以编程方式验证该用户的最佳方法是什么?
代码非常简单---问题是groupPath字符串中有一个无效字符(确切地说是'/').
我想要做的事情(至少作为一个停止差距)是跳过DirectoryEntries我无法获得cn - 无论为什么.
但是,当我运行此代码时,catch块不会运行,而是我得到:服务器无法运行.和未处理的System.Runtime.InteropServices.COMException.
为什么catch阻止不会捕获此异常.
try
{
using (DirectoryEntry groupBinding = new DirectoryEntry("LDAP://" + groupPath))
{
using (DirectorySearcher groupSearch = new DirectorySearcher(groupBinding))
{
using (DirectoryEntry groupEntry = groupSearch.FindOne().GetDirectoryEntry())
{
results.Add(string.Format("{0}", groupEntry.Properties["cn"].Value.ToString()));
}
}
}
}
catch
{
Logger.Error("User has bad roles");
}
Run Code Online (Sandbox Code Playgroud)
附加观察:代码实际上是在一个自定义的RoleProvider中,好奇的是,如果我在一个简单的winforms应用程序中引用这个提供程序,并使用相同的输入调用这个相同的方法,那么catch块就会完全按照它的设想执行.我认为这表明有关.NET异常与COM异常的建议答案并不准确.虽然我无法理解为什么从WebDev服务器执行时此代码无法捕获
是否可以使用单个PrincipalSearcher调用搜索多个用户名.也许通过提供所请求的用户名的"OR"作为过滤器标准?
当我尝试更新UserPrincipal(Principal,真的)上的Name字段(对应于CN)时,我在调用UserPrincipal.Save()时收到错误"服务器不愿意处理请求".
我已经检查过以确保同一个OU中没有其他对象具有相同的名称(CN).
我正在运行的PrincipalContext是域根(不完全在用户帐户所在的OU级别).
这个错误可能有什么原因?是否可能与安全策略相关(即使我能够更新所有其他字段)?
using (var context = new PrincipalContext(ContextType.Domain, ConfigurationManager.AppSettings["domain"], ConfigurationManager.AppSettings["rootDN"], ContextOptions.Negotiate, ConfigurationManager.AppSettings["username"], ConfigurationManager.AppSettings["password"])) {
var user = UserPrincipal.FindByIdentity(context, IdentityType.Sid, "..."); // SID abbreviated
user.Name = "Name, Test";
user.Save();
}
Run Code Online (Sandbox Code Playgroud)
我用来创建PrincipalContext的用户具有修改AD对象的安全权限.如果我更新任何其他字段(例如Surname,GivenName),一切正常.
编辑:
我已经能够完成我需要做的事情(使用ADSI),但我必须在模拟下运行以下代码.模拟代码是丑陋的,下面的代码脱离了我正在更新AD数据的另一种方式(使用DirectoryServices.AccountManagement),所以我想得到一个更好的解决方案.
using (var companyOU = new DirectoryEntry("LDAP://" + company.UserAccountOU)) {
companyOU.Invoke("MoveHere", "LDAP://" + user.DistinguishedName, "cn=Name\, Test");
}
Run Code Online (Sandbox Code Playgroud) 所以我有一个问题,老实说我不太确定该怎么问.基本上我运行时有一些代码可以在我的本地机器上运行.一旦我将它发布到我们的开发Web服务器,它就会失败.我不确定这是IIS安装问题,web.config问题还是编码问题.
这是代码片段
bool isMember = false;
PrincipalContext ADDomain = new PrincipalContext(ContextType.Domain);
UserPrincipal user = UserPrincipal.FindByIdentity(ADDomain, userID);
if (user.IsMemberOf(ADDomain, IdentityType.Name, groupName.Trim()))
{
isMember = true;
}
return isMember;
Run Code Online (Sandbox Code Playgroud)
我传入用户名和组的地方,它告诉我该用户是否是该组中的成员.没问题.在我的机器上工作得很好.我将该代码发布到网络服务器,当它到达该行时它就失败了
UserPrincipal user = UserPrincipal.FindByIdentity(ADDomain, userID);
Run Code Online (Sandbox Code Playgroud)
它会抛出此错误:
[DirectoryServicesCOMException(0x80072020):发生操作错误.]
System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)+788
System.DirectoryServices.DirectoryEntry.Bind()+44
System.DirectoryServices.DirectoryEntry.get_AdsObject()+ 42
System.DirectoryServices .PropertyValueCollection.PopulateList()+29
System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry,String propertyName)+63
System.DirectoryServices.PropertyCollection.get_Item(String propertyName)+163 System.DirectoryServices.AccountManagement.PrincipalContext.DoLDAPDirectoryInitNoContainer()+ 521217
System.DirectoryServices.AccountManagement.PrincipalContext.DoDomainInit()51
System.DirectoryServices.AccountManagement.PrincipalContext.Initialize()141
System.DirectoryServices.AccountManagement.PrincipalContext.get_QueryCtx()42
System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithTypeHelper( PrincipalContext上下文,类型principalType,Nullable`1 identityType,Str ing IdentityValue,DateTime refDate)+29
System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext context,String identityValue)+95
Cosmic.Web.Login.btnSubmit_Click(Object sender,EventArgs e)在C:\ cosmic\Cosmic.Web\Login.aspx.cs:79
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)+154
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,Boolean includeStagesAfterAsyncPoint)+3691
任何可能失败的想法?
我实现了一个返回Active Directory用户列表的方法,我想像这样检索SAMAccountName Domain\Administrator.
这是我使用的方法:
public Collection<software_user> GetUsersFromAD(String adConnectionString)
{
var users = new Collection<software_user>();
using (var directoryEntry = new DirectoryEntry(adConnectionString))
{
var directorySearcher = new DirectorySearcher(directoryEntry);
directorySearcher.Filter = "(&(objectClass=user))";
var propertiesToLoad = new[]
{
"SAMAccountName",
"displayName",
"givenName",
"sn",
"mail",
"userAccountControl",
"objectSid"
};
directorySearcher.PropertiesToLoad.AddRange(propertiesToLoad);
foreach (SearchResult searchEntry in directorySearcher.FindAll())
{
var userEntry = searchEntry.GetDirectoryEntry();
var ldapUser = new software_user();
ldapUser.User_name = NullHandler.GetString(userEntry.Properties["displayName"].Value);
if (string.IsNullOrEmpty(ldapUser.User_name))
continue;
ldapUser.User_name = NullHandler.GetString(userEntry.Properties["SAMAccountName"].Value);
ldapUser.email = NullHandler.GetString(userEntry.Properties["mail"].Value);
ldapUser.user_shortname = NullHandler.GetString(userEntry.Properties["givenName"].Value);
var userAccountControl = (int)userEntry.Properties["userAccountControl"].Value;
//ldapUser.IsActive = …Run Code Online (Sandbox Code Playgroud)