使用 AD 的服务帐户和用户帐户凭据连接到 Active Directory 以登录(在我的产品中)

Posted

技术标签:

【中文标题】使用 AD 的服务帐户和用户帐户凭据连接到 Active Directory 以登录(在我的产品中)【英文标题】:Connect to Active Directory for Login (in my product) using Service Account and User Account Credentials of AD 【发布时间】:2019-03-18 18:54:32 【问题描述】:

我目前正在使用 Directory Searcher 对 AD 用户进行身份验证。

  DirectoryEntry adsEntry = new DirectoryEntry(ConfigurationManager.AppSettings["ADConnectionString"], username, password, System.DirectoryServices.AuthenticationTypes.Secure);
  DirectorySearcher adsSearcher = new DirectorySearcher(adsEntry);

  adsSearcher.Filter = "(sAMAccountName=" + _userName + ")";

  SetPropertiesToLoad(ref adsSearcher);


  SearchResult adsSearchResult = adsSearcher.FindOne();
  Logger.Debug("After adsSearcher.FindOne() success");

  if (!ExtractPropertiesReceivedFromAD(adsSearchResult, ref emailAddress, ref _name, username, ref errorMessage))
                return false;

这适用于许多 AD 设置,但最近我遇到了其中 1 个 AD 不允许连接到它。

我的客户说他们有 LDAP 身份验证,所以我不能在不提供服务帐户凭据的情况下直接查询 AD。

所以在这种情况下,要使用 LDAP 与 AD 连接,我需要 1 个凭据,然后发布以验证用户身份,我需要他自己的用户名/密码。

现在我如何在 DirectorySearcher 中适应这种情况?

【问题讨论】:

DirectoryEntry 具有用户名和密码的属性。见:***.com/questions/10742661/… 我已经用过了。它不起作用。 您是要查找用户还是验证用户?如果您只是想查找它们,请将您的用户名和密码设置为第一行中的服务帐户。如果您尝试同时执行这两项操作,则根据您的情况可能无法实现。如果不尝试以其他用户的身份连接,则无法验证其他用户的用户名和密码。您需要使用待验证用户的凭据绑定到 AD。执行查询以查找详细信息可能需要未授予待验证用户帐户的不同权限。 我正在尝试对用户进行身份验证。是否有任何官方链接可以帮助我理解这一点(以及示例 c# 代码会更有帮助)。 在此处查看一些替代方案(包括PrincipalContext 答案):***.com/questions/290548/… - 您将不得不尝试使用用户的用户名和密码以一种或另一种方式连接到 AD。 【参考方案1】:

这是我用来使用系统凭据绑定到 LDAP 目录的函数,搜索提供的用户 ID,然后验证提供的用户凭据。要将函数与 Active Directory 一起使用,“strUIDAttr”是 sAMAccountName。

protected string ldapAuthTest(string strLDAPServer, string strSuppliedUser, string strSuppliedPwd, string strSystemUID, string strSystemPwd, string strLDAPUserBase, string strUIDAttr)

    strSuppliedUser = strSuppliedUser.Trim();
    string strResults = "";
    string strLDAPUserHost = strLDAPServer + strLDAPUserBase;

    // Establish LDAP connection and bind with system ID
    System.DirectoryServices.DirectoryEntry dirEntry = new System.DirectoryServices.DirectoryEntry();
    dirEntry.Path = strLDAPUserHost;
    dirEntry.Username = strSystemUID;
    dirEntry.Password = strSystemPwd;

    //dirEntry.AuthenticationType = System.DirectoryServices.AuthenticationTypes.None;
    dirEntry.AuthenticationType = System.DirectoryServices.AuthenticationTypes.SecureSocketsLayer;
    try
    
        dirEntry.RefreshCache();

        // Search directory for the user logging on
        string strLDAPFilter = "(&(" + strUIDAttr + "=" + strSuppliedUser + "))";
        System.DirectoryServices.DirectorySearcher ldapSearch = new System.DirectoryServices.DirectorySearcher(dirEntry);
        ldapSearch.ServerTimeLimit = new TimeSpan(0, 0, 30);


        ldapSearch.Filter = strLDAPFilter;
        ldapSearch.SearchScope = System.DirectoryServices.SearchScope.Subtree;

        System.DirectoryServices.SearchResultCollection searchResults = ldapSearch.FindAll();


        if (searchResults.Count == 1)
        
        string strLogonUserBase = searchResults[0].GetDirectoryEntry().Path;
        // get rid of strLDAPServer from directory entry path
        string strLogonUserFQDN = strLogonUserBase.Replace(strLDAPServer, "");
        dirEntry.Close();

        // Attempt to bind as the user
        System.DirectoryServices.DirectoryEntry userAuthAttempt = new System.DirectoryServices.DirectoryEntry();
        userAuthAttempt.Path = strLDAPUserHost;
        userAuthAttempt.Username = strLogonUserFQDN;
        userAuthAttempt.Password = strSuppliedPwd;
        //userAuthAttempt.AuthenticationType = System.DirectoryServices.AuthenticationTypes.None;
        userAuthAttempt.AuthenticationType = System.DirectoryServices.AuthenticationTypes.SecureSocketsLayer;
        try
        
            userAuthAttempt.RefreshCache();
            userAuthAttempt.Close();
            strResults = "<td><font color='green'>User " + UserName.Value + " has authenticated successfully.</font></td>";
        
        catch (Exception e)
        
            string strAuthError = e.Message;
            string strLockedOut = "A constraint violation occurred.\r\n";
            string strBadPwd = "Logon failure: unknown user name or bad password.\r\n";
            string strNSAccountLock = "The server is unwilling to process the request.\r\n";
            if (String.Compare(strAuthError, strBadPwd) == 0)
                strResults = "<td><font color='red'>Logon failure for user " + UserName.Value + " - password is invalid.</font></td></tr>"; ;
            
            else if (String.Compare(strAuthError, strLockedOut) == 0)
            
            strResults = "<td><font color='red'>Logon failure for user " + UserName.Value + " - account is locked out.</font></td>"; ;
            
            else if (String.Compare(strAuthError, strNSAccountLock) == 0)
            
            strResults = "<td><font color='red'>Logon failure for user " + UserName.Value + " - password has expired.</font></td>"; ;
            
            else
            
            strResults = "<td><font color='red'>Logon failure for user " + UserName.Value + " (" + strLogonUserFQDN + ") :" + strAuthError + "</font></td>"; ;
            
        
        
        else if (searchResults.Count > 1)
        
        strResults = "<td><font color='red'>Account " + UserName.Value + " was found in the directory " + searchResults.Count + " times. Please contact the Help Desk to have this issue corrected.</font></td>"; ;
        
        else
        
        strResults = "<td><font color='red'>Account " + UserName.Value + " was not found in the directory.</font></td>"; ;
        
        return strResults;
    
    catch(Exception e)
    
        string strAuthError = e.Message;
        string strConnectFail = "The server is not operational.\r\n";
        if (String.Compare(strAuthError, strConnectFail) == 0)
        
        strResults = "<td><font color='red'>Transient connection failure, please try again.</font></td>"; ;
        
        else
        
        strResults = "<td><font color='red'>Transient failure (" + strAuthError + "), please try again.</font></td>";
        
        return strResults;
    

【讨论】:

以上是关于使用 AD 的服务帐户和用户帐户凭据连接到 Active Directory 以登录(在我的产品中)的主要内容,如果未能解决你的问题,请参考以下文章

具有特定 AD 帐户凭据的连接字符串

在 Cognito 中链接第三方应用程序帐户

将 Azure AD B2C 用户连接到我的数据库帐户的正确 Core 3.0 API 中间件?

使用 Snowflake 凭据连接到 SnowSQL 客户端

来自IIS的AD帐户信息而不是来自web.config

将服务连接到现有的流星帐户