Active Directory - 检查用户名/密码

Posted

技术标签:

【中文标题】Active Directory - 检查用户名/密码【英文标题】:Active Directory - Check username / password 【发布时间】:2010-09-28 21:20:55 【问题描述】:

我在 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()

我已尝试更改身份验证类型,但不确定发生了什么。


另见:Validate a username and password against Active Directory?

【问题讨论】:

这真的是一模一样的吗?此人收到异常消息,而不是询问如何操作... 由于您使用的是 .NET 3.5,因此您可以选择使用 System.DirectoryServices.AccountManagement。我没有在工作中使用 Vista,但由于它是为 3.5 设计的,它可能与 Vista 更兼容... 我不会把这叫做骗子...... 无论如何我想通了在同一个域中 【参考方案1】:

绑定到 LDAP 是否需要提升权限 (UAC)?您可以尝试以管理员身份运行 Visual Studio 和/或应用程序,看看是否有帮助。如果这是问题所在,您可以随时向应用程序添加清单并将其设置为需要提升,这样当用户运行它时它会提示。

不知道为什么它需要提升权限,但值得一试。

【讨论】:

以管理员身份运行没有帮助【参考方案2】:

无论如何我想通了

【讨论】:

你应该可以通过 user@domain 来更改域【参考方案3】:

如果您使用的是 .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,您的意思是我们在定义主体上下文时不需要提供域名?那么它如何知道它应该验证哪个域呢?另外,请您指点我的文档,我找不到它。【参考方案4】:

我发现相同的代码在 Internet 上的多个网站上流传,但它对我不起作用。 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。请注意我是如何在两个参数之间使用“按位或”('|') 运算符设置安全 (Kerberos) 身份验证和 SSL。

第二行强制“entry”的 NativeObject 使用第一行的信息绑定到 AD 服务。

如果抛出异常,则凭据(或设置)不正确。如果没有例外,则您已通过身份验证。异常消息通常会指出出了什么问题。

此代码与您已有的代码非常相似,但在您拥有“路径”的地方使用域,并且用户名未与域结合。确保也正确设置您的 AuthenticationTypes。这可以决定身份验证能力的成败。

【讨论】:

这个问题与.Net 3.5有关;不是 .Net 2.0。 这是我见过的第一个结合了 Secure 和 SecureSocketsLayer 标志的答案,这是我设法使它工作的唯一方法。谢谢!

以上是关于Active Directory - 检查用户名/密码的主要内容,如果未能解决你的问题,请参考以下文章

用于检查 Active Directory 用户是不是上次登录的 Powershell 脚本

根据 Active Directory 策略检查密码 [重复]

在 Java 应用程序中检查使用 Active Directory 登录的用户

Java Active Directory LDAP - 使用密码哈希对用户进行身份验证

使用 Powershell 清理孤立的 Active Directory 用户配置文件文件夹

Active Directory 健康检查