首页 文章

Active Directory - 检查用户名/密码

提问于
浏览
35

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

我试过更改身份验证类型,我不确定发生了什么 .


See alsoValidate a username and password against Active Directory?

4 回答

  • 8

    如果您使用的是.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();
    
  • 0

    我在多个网站上发现相同的代码在互联网上浮动,但它对我不起作用 . 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 .

    第二行使用第一行中的信息强制将“条目”的NativeObject绑定到AD服务 .

    如果抛出异常,则凭据(或设置)很糟糕 . 如果没有例外,您将通过身份验证 . 异常消息通常表明出了什么问题 .

    此代码与您已有的代码非常相似,但在具有“路径”的位置使用域,并且用户名不与域结合使用 . 请务必正确设置AuthenticationTypes . 这可以决定身份验证的能力 .

  • 1

    我无论如何想出来如果你在vista上使用用户名传递域名它不像“域\用户”那样工作,所以只是传递“用户”似乎工作正常 - 除了你必须在同一个域

  • 50

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

    不知道为什么它需要提升私人,但它值得一试 .

相关问题