【问题标题】:LdapConnection SearchRequest throws exception for "The size limit was exceeded"LdapConnection SearchRequest 为“超出大小限制”引发异常
【发布时间】:2014-07-15 03:30:59
【问题描述】:

因为我们需要使用 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);
        }

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

超出大小限制

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

异常详情: System.DirectoryServices.Protocols.DirectoryOperationException:超出大小限制

来源错误:

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

messageId、LdapOperation 操作、ResultAll resultType、TimeSpan requestTimeOut, 布尔异常OnTimeOut) +2385 System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest 请求,时间跨度请求超时)+499 System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest 请求)+50 UserSearchProvider.ADUserSearchProvider.QueryStore(UserSearchCriteriaCollection 标准,Action1 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 工作室 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\UserSearchProvider.cs:77 UserSearchProvider.UserSearchProvider.Search(UserSearchCriteriaCollection 标准,Action1 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 工作室 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\UserSearchService.cs:44 c:\Users\stemarie\Documents\Visual Studio 中的 UserSearchProviderTest._Default.Page_Load(Object sender, EventArgs e) 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProviderTest\Default.aspx.cs:28

让我感到困惑的部分是我们确实指定了最大大小限制,我们不希望超过 100 个条目 - 我们想要限制它。但是,即使我们将 SizeLimit 指定为 1,该库也会始终抛出错误。

是否有人对此问题有任何见解/建议?我们非常接近让这项工作正常进行,只需要解决最后一个问题。

【问题讨论】:

  • 有多少目录条目与您的搜索匹配?如果删除 SizeLimit 行会发生什么?如果 sizelimit 的值低于服务器页面大小,似乎 sizelimit 将失败。我想你应该尝试发出分页搜索见stackoverflow.com/q/1646518/1236044
  • 我确实在请求中发出了分页搜索控件,但得到的响应是服务器不支持分页搜索。
  • 我不知道有多少条目可以匹配我的搜索,但我只想要其中的 100 个。代码的目的是为我们的产品创建一个在 LDAPS 中执行“用户搜索”的组件——这个库不是一个 frankenlibrary——我们希望它是一个非常强大的 LDAPS 用户搜索(适配器模式)库,以便我们可以提供这给我们的客户。所以我无法预测用户输入以及这对图书馆意味着多少结果。
  • 在此页面go4answers.webhost4life.com/Example/… 上说:“是的,您可以捕获异常并查看其 Response.Entries 属性!”我认为值得一试;-)
  • 找到了 - 我需要将 Exception.Response 转换为 SearchResponse - 然后我得到所有结果!

标签: c# .net ldap


【解决方案1】:

您应该在与此类似的功能中使用 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;
}

【讨论】:

  • 今天遇到这个错误...“分页”请求对我有用。
  • 这是解决此特定问题的最佳方法。在这种情况下,我更喜欢 do-while 循环。删除“if (pageResponseControl.Cookie.Length == 0)”和以下 break 语句的位置。并使 while 条件 pageRequestControl.Cookie.Length > 0.
【解决方案2】:

事实证明,这是可行的:

            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>();
            }

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

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

【讨论】:

  • 我认为,这个解决方案的一个问题是,您没有得到所有搜索响应,只有达到 SizeLimit 的响应。更正确的解决方案是提取您从 Ex.Response 收到的响应,然后重新运行 SendRequest,但以某种方式将范围限制为您尚未检索到的内容...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-09
  • 1970-01-01
  • 1970-01-01
  • 2019-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多