0

TLDR; これはよくできた質問ではないので、気にしないでください。スタックオーバーフローで質問しない方法の良い例である以外に、何らかの償還機能があると人々が考えない限り、近い将来に削除します。

プロジェクトの 1 つで 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 で失敗します。

皆さんへの私の質問は、なぜ 2 つの実装の動作が異なるのですか? 同じCookieが2回使用されると例外がスローされるため、新しいリクエストごとに受信したCookieを送信していることを知っています。また、各ページで返されるエントリのセットが異なるため、結果の後続のページを取得していることもわかっていると思います。

私は困惑しており、トラフィックを分析するために Ettercap を引きずり出すという考えを楽しんでいません。確かに、私のコードには明らかに間違った何かがあり、それが異なる動作を引き起こしています。

4

2 に答える 2

1

さて、2つのバグとRFCの落とし穴:

  • (バグ)結果の結果への連結は(concat(.getSearchEntries result)results)、
  • (バグ)ループの下部にある「when-not」テストは、「if」または「if-not」である必要があります。
  • (落とし穴)RFCのセクション6「セキュリティの考慮事項」の下で、「サーバーの実装はオーバーライドするサイズ制限を強制する可能性があります」、つまり、非特権ユーザーとして、制限、ページングされた結果、またはいいえ。実装間の動作の違いは、管理者権限でJavaコードを実行し、Clojureコードを匿名で実行したことによるものです(doh!)。
于 2012-03-07T17:58:23.113 に答える
1

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

コントロールを単一の結果コントロール オブジェクトのベクトルにバインドします。このベクトルは次に渡されます

(.setControls control)

これは、Javaコードのようにベクトルではなく、単一の結果コントロールオブジェクトを取るようです。

于 2012-03-07T08:32:46.067 に答える