我有一个客户端正在使用我编写的Windows服务,该服务为该LDAP服务器中指定组中的用户轮询指定的活动目录LDAP服务器。
一旦找到用户,它就会填写用户信息(即用户名,电子邮件等),并尝试在该LDAP服务器中检索用户的域。
当我尝试检索此特定客户端的用户域时,我遇到了DirectoryServicesCOMException:登录失败:unkonwn用户名或密码错误。 当我尝试在我实例化的RootDSE DirectoryEntry对象上引用属性时抛出此异常。
此客户端有一个具有两个根的林,设置如下。
Active Directory域和信任
ktregression.com
ktregression.root
我认为这是个问题。 有没有办法解决?还有什么方法可以检索特定域对象的netbiosname而不会遇到此异常?
以下是一些示例代码,指向以前记录的测试AD服务器设置:
string domainNameLdap = "dc=tempe,dc=ktregression,dc=com";
DirectoryEntry RootDSE = new DirectoryEntry (@"LDAP://10.32.16.6/RootDSE");
DirectoryEntry servers2 = new DirectoryEntry (@"LDAP://cn=Partitions," + RootDSE.Properties["configurationNamingContext"].Value ); //*****THIS IS WHERE THE EXCEPTION IS THROWN********
//Iterate through the cross references collection in the Partitions container
DirectorySearcher clsDS = new DirectorySearcher(servers2);
clsDS.Filter = "(&(objectCategory=crossRef)(ncName=" + domainNameLdap + "))";
clsDS.SearchScope = SearchScope.Subtree;
clsDS.PropertiesToLoad.Add("nETBIOSName");
List<string> bnames = new List<string>();
foreach (SearchResult result in clsDS.FindAll() )
bnames.Add(result.Properties["nETBIOSName"][0].ToString());
答案 0 :(得分:2)
似乎Active Directory尝试对您进行身份验证的用户帐户不存在,因为DirectoryServicesCOMException
会对其进行身份验证。
DirectoryServicesCOMException:登录失败:unkonwn用户名或密码错误。
查看您的代码示例,似乎您没有使用模拟,因此Active Directory的安全协议会考虑当前经过身份验证的用户。自己创建这个用户,然后如果你没有在你的两个域根目录上定义,那么其中一个人就不会知道你,这会引发这种异常。
另一方面,使用模拟可能会解决此问题,因为您说您的Windows服务帐户有权在同一个林下查询您的根,那么您必须确保经过身份验证的用户是您的Windows服务。
清楚,这意味着在没有模拟的情况下,您无法保证经过身份验证的用户是您的Windows服务。为了确保这一点,模仿是必须使用的。
现在,关于两个根
这是两个不同的独立根源。因此,我猜你应该使用DirectoryEntry
类的两个实例为每个根拟合一个。
在实例化根之后,您需要搜索要查找的用户,该用户应该是另一个与模拟的用户不同的 userName 。
我们现在必须说明是否可以在两个根上定义用户。如果是这样,你需要知道什么时候选择一个而不是另一个。这是另一个问题。
注意强>
为了简单起见,我会认为两个根的名字都是完整的/完整的,就像你提到的那样。
private string _dotComRootPath = "LDAP://ktregression.com";
private string _dotRootRootPath = "LDAP://ktregression.root";
private string _serviceAccountLogin = "MyWindowsServiceAccountLogin";
private string _serviceAccountPwd = "MyWindowsServiceAccountPassword";
public string GetUserDomain(string rootPath, string login) {
string userDomain = null;
using (DirectoryEntry root = new DirectoryEntry(rootPath, _serviceAccountLogin, _serviceAccountPwd))
using (DirectorySearcher searcher = new DirectorySearcher()) {
searcher.SearchRoot = root;
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.Add("nETBIOSName");
searcher.Filter = string.Format("(&(objectClass=user)(sAMAccountName={0}))", login);
SearchResult result = null;
try {
result = searcher.FindOne();
if (result != null)
userDomain = (string)result.GetDirectoryEntry()
.Properties("nETBIOSName").Value;
} finally {
dotComRoot.Dispose();
dotRootRoot.Dispose();
if (result != null) result.Dispose();
}
}
return userDomain;
}
使用它:
string userDomain = (GetUserDomain(_dotComRoot, "searchedLogin")
?? GetUserDomain(_dotRootRoot, "searchedLogin"))
?? "Unknown user";
您的例外仅在第二次DirectoryEntry
初始化时抛出,这表明您的默认当前用户没有在此根目录上定义帐户。
编辑#1
请参阅下面对您的其他NetBIOS名称相关问题的回答:
的 C# Active Directory: Get domain name of user? 强>
在那里,我为您的关注提供了一种新的,可能更简单的解决方案。
如果您有任何进一步的问题,请与我们联系。 =)
答案 1 :(得分:0)
我认为DirectoryEntry具有为可以执行LDAP查询或更新的AD帐户指定的属性,您也可以从父域委派该控件。