如何对活动目录验证用户名和密码?我只是想检查用户名和密码是否正确。


当前回答

我使用这个过程作为DLL登录到我们开发的其他应用程序… (我们目前正在使用OpenEdge Progress)

public static string AzureLogin(string user, string password) {

    string status;

    try {
        new DirectorySearcher(new DirectoryEntry("LDAP://yourdomain.com", user, password) {
            AuthenticationType = AuthenticationTypes.Secure,
            Username = user,
            Password = password
        })  {
            Filter = "(objectclass=user)"
        }.FindOne().Properties["displayname"][0].ToString();

        status = $"SUCCESS - User {user} has logged in.";

    } catch(System.Exception e) {
        status = $"ERROR - While logging in: {e}";
    }

    return status;
}

其他回答

这里介绍的几个解决方案缺乏区分错误用户/密码和需要更改的密码的能力。这可以通过以下方式来实现:

using System;
using System.DirectoryServices.Protocols;
using System.Net;

namespace ProtocolTest
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                LdapConnection connection = new LdapConnection("ldap.fabrikam.com");
                NetworkCredential credential = new NetworkCredential("user", "password");
                connection.Credential = credential;
                connection.Bind();
                Console.WriteLine("logged in");
            }
            catch (LdapException lexc)
            {
                String error = lexc.ServerErrorMessage;
                Console.WriteLine(lexc);
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc);
            }
        }
    }
}

如果用户密码错误,或者用户不存在,error将包含

“8009030C: LdapErr: DSID-0C0904DC,注释:AcceptSecurityContext错误,数据52e, v1db1”,

如果用户密码需要修改,则包含

"8009030C: LdapErr: DSID-0C0904DC,注释:AcceptSecurityContext错误,数据773,v1db1"

lexc。ServerErrorMessage数据值是Win32错误码的十六进制表示。这些是通过调用Win32 LogonUser API调用返回的相同错误代码。下面的列表总结了一些常见的十六进制和十进制值:

525​ user not found ​(1317)
52e​ invalid credentials ​(1326)
530​ not permitted to logon at this time​ (1328)
531​ not permitted to logon at this workstation​ (1329)
532​ password expired ​(1330)
533​ account disabled ​(1331) 
701​ account expired ​(1793)
773​ user must reset password (1907)
775​ user account locked (1909)

我使用这个过程作为DLL登录到我们开发的其他应用程序… (我们目前正在使用OpenEdge Progress)

public static string AzureLogin(string user, string password) {

    string status;

    try {
        new DirectorySearcher(new DirectoryEntry("LDAP://yourdomain.com", user, password) {
            AuthenticationType = AuthenticationTypes.Secure,
            Username = user,
            Password = password
        })  {
            Filter = "(objectclass=user)"
        }.FindOne().Properties["displayname"][0].ToString();

        status = $"SUCCESS - User {user} has logged in.";

    } catch(System.Exception e) {
        status = $"ERROR - While logging in: {e}";
    }

    return status;
}

这里是我完整的认证解决方案,供您参考。

首先,添加以下四个引用

 using System.DirectoryServices;
 using System.DirectoryServices.Protocols;
 using System.DirectoryServices.AccountManagement;
 using System.Net; 

private void AuthUser() { 


      try{
            string Uid = "USER_NAME";
            string Pass = "PASSWORD";
            if (Uid == "")
            {
                MessageBox.Show("Username cannot be null");
            }
            else if (Pass == "")
            {
                MessageBox.Show("Password cannot be null");
            }
            else
            {
                LdapConnection connection = new LdapConnection("YOUR DOMAIN");
                NetworkCredential credential = new NetworkCredential(Uid, Pass);
                connection.Credential = credential;
                connection.Bind();

                // after authenticate Loading user details to data table
                PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
                UserPrincipal user = UserPrincipal.FindByIdentity(ctx, Uid);
                DirectoryEntry up_User = (DirectoryEntry)user.GetUnderlyingObject();
                DirectorySearcher deSearch = new DirectorySearcher(up_User);
                SearchResultCollection results = deSearch.FindAll();
                ResultPropertyCollection rpc = results[0].Properties;
                DataTable dt = new DataTable();
                DataRow toInsert = dt.NewRow();
                dt.Rows.InsertAt(toInsert, 0);

                foreach (string rp in rpc.PropertyNames)
                {
                    if (rpc[rp][0].ToString() != "System.Byte[]")
                    {
                        dt.Columns.Add(rp.ToString(), typeof(System.String));

                        foreach (DataRow row in dt.Rows)
                        {
                            row[rp.ToString()] = rpc[rp][0].ToString();
                        }

                    }  
                }
             //You can load data to grid view and see for reference only
                 dataGridView1.DataSource = dt;


            }
        } //Error Handling part
        catch (LdapException lexc)
        {
            String error = lexc.ServerErrorMessage;
            string pp = error.Substring(76, 4);
            string ppp = pp.Trim();

            if ("52e" == ppp)
            {
                MessageBox.Show("Invalid Username or password, contact ADA Team");
            }
            if ("775​" == ppp)
            {
                MessageBox.Show("User account locked, contact ADA Team");
            }
            if ("525​" == ppp)
            {
                MessageBox.Show("User not found, contact ADA Team");
            }
            if ("530" == ppp)
            {
                MessageBox.Show("Not permitted to logon at this time, contact ADA Team");
            }
            if ("531" == ppp)
            {
                MessageBox.Show("Not permitted to logon at this workstation, contact ADA Team");
            }
            if ("532" == ppp)
            {
                MessageBox.Show("Password expired, contact ADA Team");
            }
            if ("533​" == ppp)
            {
                MessageBox.Show("Account disabled, contact ADA Team");
            }
            if ("533​" == ppp)
            {
                MessageBox.Show("Account disabled, contact ADA Team");
            }



        } //common error handling
        catch (Exception exc)
        {
            MessageBox.Show("Invalid Username or password, contact ADA Team");

        }

        finally {
            tbUID.Text = "";
            tbPass.Text = "";

        }
    }

试试这段代码 (注意:报告不能在windows server 2000上工作)

#region NTLogonUser
#region Direct OS LogonUser Code
[DllImport( "advapi32.dll")]
private static extern bool LogonUser(String lpszUsername, 
    String lpszDomain, String lpszPassword, int dwLogonType, 
    int dwLogonProvider, out int phToken);

[DllImport("Kernel32.dll")]
private static extern int GetLastError();

public static bool LogOnXP(String sDomain, String sUser, String sPassword)
{
   int token1, ret;
   int attmpts = 0;

   bool LoggedOn = false;

   while (!LoggedOn && attmpts < 2)
   {
      LoggedOn= LogonUser(sUser, sDomain, sPassword, 3, 0, out token1);
      if (LoggedOn) return (true);
      else
      {
         switch (ret = GetLastError())
         {
            case (126): ; 
               if (attmpts++ > 2)
                  throw new LogonException(
                      "Specified module could not be found. error code: " + 
                      ret.ToString());
               break;

            case (1314): 
               throw new LogonException(
                  "Specified module could not be found. error code: " + 
                      ret.ToString());

            case (1326): 
               // edited out based on comment
               //  throw new LogonException(
               //   "Unknown user name or bad password.");
            return false;

            default: 
               throw new LogonException(
                  "Unexpected Logon Failure. Contact Administrator");
              }
          }
       }
   return(false);
}
#endregion Direct Logon Code
#endregion NTLogonUser

除非你需要为“LogonException”创建自己的自定义异常

不幸的是,没有“简单”的方法来检查AD上的用户凭据。

使用到目前为止所介绍的每一种方法,你可能会得到一个假阴性:用户的信用将是有效的,但AD在某些情况下将返回false:

用户需要在下次登录时更改密码。 用户密码已过期。

ActiveDirectory不允许您使用LDAP来确定密码是否由于用户必须更改密码或密码是否过期而无效。

要确定密码更改或密码过期,您可以调用Win32:LogonUser(),并检查以下2个常量的windows错误码:

Error_password_must_change = 1907 Error_password_expired = 1330