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