2012-11-26 37 views
6

LDAPSを使用してLDAPサーバーに接続する必要があるため、DirectoryEntryではなくLdapConnectionを使用する必要があります。ここでLdapConnection SearchRequestが「サイズ制限を超えました」の例外をスローします

ソースコードです:ソースコードが実行されると

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

(私たちは資格情報、ホスト、ポート、などを確認しました - 外部のサードパーティ製のソフトウェアを使用して)私たちは、次の例外を取得:

未処理の例外が現在のWeb要求の実行中に発生しました:

サイズ制限が

説明を超えました。エラーの詳細とコード内のどこで発生したのかについては、スタックトレースを参照してください。

例外の詳細: System.DirectoryServices.Protocols.DirectoryOperationException:

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

messageId, LdapOperation operation, 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, Action 1 logMessage) in c:\Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\UserSearchProvider.cs:77 UserSearchProvider.UserSearchProvider.Search(UserSearchCriteriaCollection criterias, Action 1 logMessage) in c:\Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\UserSearchProvider.cs:33 UserSearchProvider.UserSearchService.Search(UserSearchCriteriaCollection criterias, Action 1 logMessage) in 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に指定しても、一貫してエラーがスローされます。

この問題に関する洞察や提案はありますか?私たちはこれを実現させることに非常に近づき、この最後の問題を解決する必要があります。

+0

検索に一致するディレクトリエントリの数はいくつですか? SizeLimit行を削除するとどうなりますか?その値がサーバーのページサイズよりも小さい場合、sizelimitは失敗するようです。私はあなたがページングされた検索を発行しようとする必要があると思うhttp://stackoverflow.com/q/1646518/1236044 – jbl

+0

私はリクエストでページングされた検索コントロールを発行したが、サーバーがページングされた検索をサポートしていないという応答を得た。 –

+0

検索に一致するエントリの数はわかりませんが、100個しか必要ありません。このコードの目的は、製品のLDAPSで「ユーザー検索」を実行するコンポーネントを作成することです。このライブラリはフランネルライブラリではありません。LDAPSのユーザー検索(アダプタパターン)ライブラリとして非常に頑丈なので、これは私たちのクライアントに。だから、私はユーザーの入力を予測する方法がなく、これがライブラリーのために何個の結果を意味するかもしれません。 –

答えて

1

結局のところ、これは動作します:

  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のドキュメントでは、DirectoryOperationException.ResponseプロパティとしてDirectoryResponseクラスを取得すると述べています。ただし、このプロパティをSearchResponse型にキャストしてから、SearchResponse.Entriesプロパティを使用して、指定したSizeLimitを打つ前に受け取ったエントリを取得できます。

これを試してみましたが、期待した結果が得られました。操作を実行するために例外を処理する必要があります。

+2

この解決策の1つの問題は、あなたが*すべての*検索レスポンス、つまりSizeLimitまでのレスポンスを取得しないということです。より正確な解決策は、Ex.Responseから受け取った応答を抽出し、次にSendRequestを再実行しますが、何らかの形で範囲をあなたがまだ検索していないものに限定することです。 – Irinotecan

6

クッキーは、このような機能で使用する必要があります。 この関数は、呼び出し元がループするはずの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; 
} 
関連する問題