我在Windows Vista Ultimate SP1上使用以下代码来查询我们的活动目录服务器以检查域上用户的用户名和密码.
public Object IsAuthenticated() { String domainAndUsername = strDomain + "\\" + strUser; DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, strPass); SearchResult result; try { //Bind to the native AdsObject to force authentication. DirectorySearcher search = new DirectorySearcher(entry) { Filter = ("(SAMAccountName=" + strUser + ")") }; search.PropertiesToLoad.Add("givenName"); // First Name search.PropertiesToLoad.Add("sn"); // Last Name search.PropertiesToLoad.Add("cn"); // Last Name result = search.FindOne(); if (null == result) { return null; } //Update the new path to the user in the directory. _path = result.Path; _filterAttribute = (String)result.Properties["cn"][0]; } catch (Exception ex) { return new Exception("Error authenticating user. " + ex.Message); } return user; }
目标是使用.NET 3.5,并使用VS 2008标准编译
我是在域帐户下登录的,该域帐户是运行应用程序的域管理员.
该代码在Windows XP上运行良好; 但是在Vista上运行时会出现以下异常:
System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password. at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail) at System.DirectoryServices.DirectoryEntry.Bind() at System.DirectoryServices.DirectoryEntry.get_AdsObject() at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne) at System.DirectoryServices.DirectorySearcher.FindOne() at Chain_Of_Custody.Classes.Authentication.LdapAuthentication.IsAuthenticated() at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail) at System.DirectoryServices.DirectoryEntry.Bind() at System.DirectoryServices.DirectoryEntry.get_AdsObject() at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne) at System.DirectoryServices.DirectorySearcher.FindOne() at Chain_Of_Custody.Classes.Authentication.LdapAuthentication.IsAuthenticated()
我试过更改身份验证类型,我不确定发生了什么.
另见:验证Active Directory的用户名和密码?
如果您使用的是.net 3.5,请使用此代码.
要对用户进行身份验证:
PrincipalContext adContext = new PrincipalContext(ContextType.Domain); using (adContext) { return adContext.ValidateCredentials(UserName, Password); }
如果需要找到用户对该对象的R/W属性,请执行以下操作:
PrincipalContext context = new PrincipalContext(ContextType.Domain); UserPrincipal foundUser = UserPrincipal.FindByIdentity(context, "jdoe");
这是使用System.DirectoryServices.AccountManagement命名空间,因此您需要将其添加到using语句中.
如果需要将UserPrincipal对象转换为DirectoryEntry对象以使用旧代码,则可以执行以下操作:
DirectoryEntry userDE = (DirectoryEntry)foundUser.GetUnderlyingObject();
我在多个网站上发现相同的代码在互联网上浮动,但它对我不起作用.Steve Evans可能是正确的,如果您使用的是.NET 3.5,则不应使用此代码.但是,如果您仍然使用.NET 2.0,则可以尝试对您的AD服务进行身份验证:
DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, userName, password, AuthenticationTypes.Secure | AuthenticationTypes.SecureSocketsLayer); object nativeObject = entry.NativeObject;
第一行使用域,用户名和密码创建DirectoryEntry对象.它还设置AuthenticationTypes.请注意我是如何使用两个参数之间的"按位OR"('|')运算符设置安全(Kerberos)身份验证和SSL.
第二行使用第一行中的信息强制将"entry"的NativeObject绑定到AD服务.
如果抛出异常,则凭据(或设置)很糟糕.如果没有例外,您将通过身份验证.异常消息通常表明出了什么问题.
此代码与您已有的代码非常相似,但域名用于"路径",用户名不与域结合使用.一定要正确设置AuthenticationTypes.这可以决定身份验证的能力.