0

TLDR;这不是一个措辞恰当的问题,因此您可能不应该为此烦恼。我会在不久的将来删除它,除非人们认为它有一些赎回功能,而不是作为如何不在 Stack Overflow 上提问的一个很好的例子。

我正在为我的一个项目使用 UnboundID LDAP SDK。我目前坚持实现分页结果搜索(在 RFC2696 中描述),为此我有一个有效的 Java 实现。我已经测试了 Java 代码,并且知道它可以在我的测试 LDAP 目录中正常工作。Java 实现的主要部分是以下 do..while 循环:

do
{
  /*
   * Set the simple paged results control (if the cookie is null
   * this indicates the first time through the loop).
   */
  final SimplePagedResultsControl simplePagedResultsRequestControl =
      new SimplePagedResultsControl(pageSize,cookie);
  searchRequest.setControls(simplePagedResultsRequestControl);

  /*
   * Issue the search request:
   */
  SearchResult searchResult;
  searchResult = ldapConnection.search(searchRequest);
  final String msg =
      String
          .format(
              "searchRequest transmitted, pageSize: %d, entries returned: %d",
              Integer.valueOf(pageSize),
              Integer.valueOf(searchResult.getEntryCount()));
  final LogRecord record = new LogRecord(Level.INFO,msg);
  ldapCommandLineTool.out(new MinimalLogFormatter().format(record));
  total += searchResult.getEntryCount();
  /*
   * Get the cookie from the paged results control.
   */
  cookie = null;
  final SimplePagedResultsControl c =
      SimplePagedResultsControl.get(searchResult);
  if(c != null)
  {
    cookie = c.getCookie();
  }
}
while(cookie != null && cookie.getValueLength() > 0);

请求“控制”被添加到搜索请求中,向服务器指示它应该发回匹配条目的子集。假设初始请求有效,LDAP 服务器返回 pageSize 条目和包含特殊“cookie”的响应控件。为了获得结果的下一个“页面”,客户端重新发送请求,cookie 包含在请求控件中,服务器在后续响应中包含一个新的 cookie。这个循环一直持续到没有更多条目要返回,在这种情况下,没有 cookie 被返回给客户端并且搜索请求完成。

我试图将上面的代码移植到 Clojure,但到目前为止我一直无法让它工作。这是代码:

(defn fetch-all
  [& attrs]
  (with-connection
    (let [attrs (into-array (if attrs (map name attrs) ["*"]))
          scope SearchScope/SUB
          request (SearchRequest. searchbase scope account-filter attrs)]
      (loop [results [] cookie nil]
        (let [control [(SimplePagedResultsControl. page-size cookie)]]
          (doto request
            (.setSizeLimit 12345)
            (.setTimeLimitSeconds 60)
            (.setControls control))
          (let [result (.search *conn* request)
                results (concat result results)
                cookie (.. SimplePagedResultsControl (get result) getCookie)]
            (println "entries returned:" (.getEntryCount result))
            (when-not (> 0 (.getValueLength cookie))
              results
              (recur
               results cookie))))))))

Java 代码通过 18 个请求检索 1720 个条目,但我的代码在 5 个请求后因“超出大小限制”LDAPSearchException 而失败。

我对你们的问题是为什么这两种实现的行为不同?我知道我会在每个新请求中发送接收到的 cookie,因为如果同一个 cookie 被使用两次,则会引发异常。我还认为我知道我正在获得后续页面的结果,因为每个页面返回的条目集是不同的。

我被难住了,不喜欢拖出 Ettercap 来分析流量的想法。当然,我的代码中有一些非常明显的错误导致了不同的行为。

4

2 回答 2

1

(let [control [(SimplePagedResultsControl. page-size cookie)]]

将控件绑定到单个结果控件对象的向量。然后将该向量传递给

(.setControls control)

这似乎将单个结果控制对象而不是向量作为您的 java 代码。

于 2012-03-07T08:32:46.067 回答
1

好的,有两个错误和 RFC 中的一个陷阱:

  • (错误)结果与结果的串联应该是(concat(.getSearchEntries 结果)结果),
  • (错误)循环底部的“when-not”测试应该是“if”或“if-not”。
  • (gotcha) 在 RFC 的第 6 节“安全注意事项”下,建议“服务器实现可能会强制执行覆盖大小限制”,也就是说,作为非特权用户,我仍然会达到限制、分页结果或不是。实现之间的行为差​​异仅仅是由于我以管理权限运行 Java 代码和匿名运行 Clojure 代码(doh!)。
于 2012-03-07T17:58:23.113 回答