7

ASP.NET MVC 4 アプリケーションでいくつかのコードを実行しています。アプリケーションは、Windows Server 2012 の IIS でホストされます。アプリケーション プールの ID は標準ではなく、特定のユーザーiis-appPool-usernameです。アプリケーションは、マネージド パイプライン用に統合モードが設定された .NET 4.0 で実行されています。

  • DirectoryEntryオブジェクト にユーザー名を指定する場合と指定しない場合の両方で試しました。
  • 同じマシン上で、まったく同じユーザー (つまり、同じユーザーとして実行される command.exe) と同じことを行うコンソール アプリを実行できます。
  • LDAP パスとを手動で指定するまで、コンソール アプリは機能しなかったことに注意してください。LDAP パスと読み取り専用タイプを指定するまで、コンソール アプリで同じエラーが発生していました。ただし、現在コンソール アプリは機能しますが、IIS アプリは機能しません。 AuthenticationTypes.ReadonlyServer

コードは以下です。

// also tried: var searchRoot = new DirectoryEntry(@"LDAP://DC=subdom,DC=ourdomain,DC=com");
var searchRoot = new DirectoryEntry(@"LDAP://DC=subdom,DC=ourdomain,DC=com", @"domain\iis-appPool-username", "password");
searchRoot.AuthenticationType = AuthenticationTypes.ReadonlyServer;

using (var searcher = new DirectorySearcher(searchRoot))
{
    searcher.Filter = string.Format("(&(objectClass=group)(sAMAccountName={0}))", "someGroupName");
    searcher.PropertiesToLoad.Add("distinguishedName");

    // This is where the failure happens
    var result = searcher.FindOne();
}

スタック トレース付きのエラーは次のようになります。

System.Runtime.InteropServices.COMException (0x8007054B): 
The specified domain either does not exist or could not be contacted.

at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_AdsObject()
at System.DirectoryServices.PropertyValueCollection.PopulateList()
at System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry, String propertyName)
at System.DirectoryServices.PropertyCollection.get_Item(String propertyName)
at System.DirectoryServices.DirectorySearcher.get_SearchRoot()
at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
at System.DirectoryServices.DirectorySearcher.FindOne()

編集:また、間違ったユーザー名とパスワードを明示的に使用すると、まったく同じエラーになります。ローカル マシンから、間違ったユーザー名とパスワードを使用すると、認証エラーが発生します。ただし、IIS からは、間違ったユーザー名とパスワードを使用すると、それほど遠くまで到達しません。

編集:完全な信頼で実行するようにweb.configで指定しました:

<securityPolicy>
    <trustLevel name="Full" policyFile="internal"/>
</securityPolicy>

また、ユーザーにボックスの管理者権限も付与しました。同じエラーが引き続き発生します。System.Runtime.InteropServices.COMException: The specified domain either does not exist or could not be contacted.

更新:したがって、これは2つの問題の組み合わせになりました。

1) @Hans が以下に記したように、もともと へのDirectoryEntryパラメーターがありませんでしたDirectorySearcher。さまざまな可能性や組み合わせを試してみたところ、コンソール アプリケーションが動作していて、それを反映するようにアプリケーション コードを更新していたときに、その変更を見逃すことがありました。

2) パラメータを に追加したときDirectorySearcher、まだエラーが発生していました。メッセージは同じで、スタック トレースもほぼ同じでした。スタック トレースの途中に 1 行の違いがありました。それは、別のメソッドへの 2 次呼び出しDirectoryEntryで、それ自体で使用する引数が必要でしたDirectorySearcher。私はこの問題を長い間見ていましたが、実際には新しいものだったのに、同じエラー メッセージと同じスタック トレースのように見えるものしか見えなかったのです。オブジェクトをこれらの呼び出しに渡すと、DirectoryEntryその問題が修正されました。

究極の解決策では、パスにサーバー識別子が含まれている必要はありませんでした (ただし、サーバー識別子がないとドメイン コントローラーを解決できない環境では、距離が異なる場合があります)。

4

1 に答える 1

5

DirectorySearcherActive Directory ドメイン コントローラに接続するには、クラスの検索ルートを指定する必要があります。クラスの検索ルートを指定しないと、COM 例外 (0x8007054B)が発生します。DirectorySearcher

代わりに、次のコード行を試してください。

var searchRoot = new DirectoryEntry(@"LDAP://DC=subdom,DC=ourdomain,DC=com", @"domain\iis-appPool-username", "password");
searchRoot.AuthenticationType = AuthenticationTypes.ReadonlyServer;

using (var searcher = new DirectorySearcher(searchRoot)) // Specify the search root here
{
  searcher.Filter = string.Format("(&(objectClass=group)(sAMAccountName={0}))", "someGroupName");
  searcher.PropertiesToLoad.Add("distinguishedName");

  var result = searcher.FindOne();
}
于 2013-09-23T18:44:18.317 に答える