LdapConnection SearchRequest抛出"超出大小限制"的异常

Kar*_*rie 6 .net c# ldap

由于我们需要使用LDAPS连接到LDAP服务器,因此我们必须使用LdapConnection而不是DirectoryEntry.

这是源代码:

        SearchResponse response;
        using (LdapConnection con = new LdapConnection(new LdapDirectoryIdentifier(Host, Port)))
        {
            if (IsSSL)
            {
                con.SessionOptions.SecureSocketLayer = true;
                con.SessionOptions.VerifyServerCertificate =
                    (connection, certificate)
                    => true;
            }
            con.Credential = new NetworkCredential(_username, _password);
            con.AuthType = AuthType.Basic;
            con.Bind();

            if (logMessage != null)
                logMessage("Connected to LDAP");

            string sFilter = String.Format(
                "(&(objectcategory=person)(objectclass=user){0}(!(userAccountControl:1.2.840.113556.1.4.803:=2)))",
                filter
                );

            SearchRequest request = new SearchRequest("OU=Corp,DC=mydc,DC=com", sFilter, SearchScope.Subtree);
            request.Attributes.Add(Resources.objectguid);
            request.Attributes.Add(Resources.givenname);
            request.Attributes.Add(Resources.sn);
            request.Attributes.Add(Resources.initials);
            request.Attributes.Add(Resources.samaccountname);
            request.Attributes.Add(Resources.userprincipalname);
            request.Attributes.Add(Resources.mail);
            request.Attributes.Add(Resources.objectsid);
            request.Attributes.Add(Resources.department);
            request.Attributes.Add(Resources.company);
            request.SizeLimit = 10;

            response = (SearchResponse) con.SendRequest(request);
        }
Run Code Online (Sandbox Code Playgroud)

执行源代码(我们使用外部第三方软件验证了凭据,主机,端口等)后,我们得到以下异常:

超出了大小限制

描述:执行当前Web请求期间发生未处理的异常.请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息.

异常详细信息: System.DirectoryServices.Protocols.DirectoryOperationException:超出了大小限制

来源错误:

response = (SearchResponse) con.SendRequest(request);
Run Code Online (Sandbox Code Playgroud)
[DirectoryOperationException: The size limit was exceeded]
   System.DirectoryServices.Protocols.LdapConnection.ConstructResponse(Int32
Run Code Online (Sandbox Code Playgroud)

messageId,LdapOperation操作,ResultAll resultType,TimeSpan requestTimeOut,Boolean exceptionOnTimeOut)+2385 System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request,TimeSpan requestTimeout)+499 System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request)+50 UserSearchProvider .ADUserSearchProvider.QueryStore(UserSearchCriteriaCollection Criterias,Action 1 logMessage) in c:\Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\ADUserSearchProvider.cs:298 UserSearchProvider.UserSearchProvider.QueryAndSort(UserSearchCriteriaCollection criterias, Action1 logMessage)在c:\ Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\UserSearchProvider.cs:77 UserSearchProvider.UserSearchProvider.Search(UserSearchCriteriaCollection standarderias,行动1 logMessage) in c:\Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\UserSearchProvider.cs:33 UserSearchProvider.UserSearchService.Search(UserSearchCriteriaCollection criterias, Action1:logMessage)在c:\ Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\UserSearchService.cs:44 UserSearchProviderTest._Default.Page_Load(Object sender,EventArgs e)in c:\ Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProviderTest\Default.aspx.cs:28

困扰我的部分是我们确实指定了最大大小限制,我们不想要超过100个条目 - 我们想要限制它.但即使我们指定SizeLimit为1,库也会一直抛出错误.

有没有人对此问题有任何见解/建议?我们非常接近这个工作,只需解决最后一个问题.

Joh*_*ohn 7

您应该在与此类似的功能中使用cookie.该函数返回一个SearchResponse对象的集合,调用者应循环该对象.

private List<SearchResponse> SearchDirectory(string distinguishedName, string searchFilter, System.DirectoryServices.Protocols.SearchScope searchScope, params string[] attributeList)
{
    List<SearchResponse> result = new List<SearchResponse>();
    SearchResponse response = null;
    int maxResultsToRequest = 100;
    try
    {
        PageResultRequestControl pageRequestControl = new PageResultRequestControl(maxResultsToRequest);

        // used to retrieve the cookie to send for the subsequent request
        PageResultResponseControl pageResponseControl;
        SearchRequest searchRequest = new SearchRequest(distinguishedName, searchFilter, searchScope, attributeList);
        searchRequest.Controls.Add(pageRequestControl);

        while (true)
        {
            response = (SearchResponse)connection.SendRequest(searchRequest);
            result.Add(response);
            pageResponseControl = (PageResultResponseControl)response.Controls[0];
            if (pageResponseControl.Cookie.Length == 0)
                break;
            pageRequestControl.Cookie = pageResponseControl.Cookie;
        }
    }
    catch (Exception e)
    {
        // do something with the error

    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)


Kar*_*rie 0

事实证明,这是有效的:

            try
            {
                response = (SearchResponse)con.SendRequest(request);

                return response.Entries.Cast<SearchResultEntry>()
                    .Select(entry => entry.Attributes)
                    .Select(x => GetADUserSearchItemFromADProperties(x, logMessage))
                    .Where(user => user.HasName)
                    .Cast<IUserSearchItem>();
            }
            catch (DirectoryOperationException ex)
            {
                response = (SearchResponse) ex.Response;
                return response.Entries.Cast<SearchResultEntry>()
                    .Select(entry => entry.Attributes)
                    .Select(x => GetADUserSearchItemFromADProperties(x, logMessage))
                    .Where(user => user.HasName)
                    .Cast<IUserSearchItem>();
            }
Run Code Online (Sandbox Code Playgroud)

MSDN 文档指出您将获得一个DirectoryResponse类作为 DirectoryOperationException.Response 属性。不过,您可以将此属性转换为SearchResponse类型,然后使用 SearchResponse.Entries 属性来获取在达到指定 SizeLimit 之前收到的条目。

我已经尝试过这个并且得到了预期的结果,我只是有点沮丧,因为我必须处理异常才能执行该操作。

  • 我认为,此解决方案的一个问题是您无法获得“所有”搜索响应,而只能获得 SizeLimit 以内的响应。更正确的解决方案是提取您从 Ex.Response 收到的响应,然后重新运行 SendRequest 但以某种方式将范围限制为您尚未检索到的内容... (2认同)