web-dev-qa-db-ja.com

System.DirectoryServices-サーバーが動作していません

Windows認証を使用しているWebサイトでエラーが発生します。

奇妙なこと:

  • ユーザーがまだデータベースに保存されていない場合にのみ発生(新しい不明なユーザー)
  • ライブシステムにのみ表示され、ローカル開発環境ではすべて問題ありません

これは私がロギングメールで受け取るものです:

ソース:System.DirectoryServices

メッセージ:サーバーは作動可能ではありません。

痕跡:
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
System.DirectoryServices.DirectoryEntry.Bind()で
System.DirectoryServices.DirectoryEntry.get_AdsObject()で
at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
at System.DirectoryServices.DirectorySearcher.FindOne()
at Smarthouse.Labs.DataAccess.UserListManager.SaveUser(String windowsUserName)

これは私がDirectorySearchを実装する方法です:

private void SaveUser(string windowsUserName)
{
    string[] domainAndUser = windowsUserName.Split('\\');
    string domain = domainAndUser[0];
    string username = domainAndUser[1];

    DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain);
    DirectorySearcher search = new DirectorySearcher(entry);

    try
    {
        // Bind to the native AdsObject to force authentication.
        search.Filter = "(SAMAccountName=" + username + ")";
        search.PropertiesToLoad.Add("cn");
        search.PropertiesToLoad.Add("sn");
        search.PropertiesToLoad.Add("givenName");
        search.PropertiesToLoad.Add("mail");

        SearchResult result = search.FindOne();

        if (result == null)
        {
            throw new Exception("No results found in Windows authentication.");
        }

        User userToSave = new User();
        userToSave.FirstName = (String) result.Properties["givenName"][0];
        userToSave.LastName = (String) result.Properties["sn"][0];
        userToSave.Email = (String) result.Properties["mail"][0];
        userToSave.Username = windowsUserName;
        userToSave.Guid = Guid.NewGuid();

        SaveUser(userToSave);
    }
    catch (Exception ex)
    {
        throw new Exception("Error authenticating user. " + ex.Message, ex);
    }
    finally
    {
        //Dispose service and search to prevent leek in memory
        entry.Dispose();
        search.Dispose();
    }
}

さらにコード例が必要な場合は、教えてください。

15
Tai Kahar

問題は、バインドに「プレーン」ドメイン名を使用していることです。これはLDAPでは機能しません。実際、LDAP://MyDomainにバインドしようとすると、本当にしているのはサーバーにバインドしようとしていることです。 )MyDomainと呼ばれます。

LDAP://dc=yourdomain,dc=localなどの有効なLDAPバインド文字列が必要です。

デフォルトのLDAPバインディングコンテキストを確認するには、次のコードスニペットを使用します。

DirectoryEntry deRoot = new DirectoryEntry("LDAP://RootDSE");

if (deRoot != null)
{
   string defaultNamingContext = deRoot.Properties["defaultNamingContext"].Value.ToString();
}

その文字列を取得したら、それをLDAPサーバーへのバインド文字列として使用します。

また、.NET 3.5以降を使用している場合は、System.DirectoryServices.AccountManagement(S.DS.AM)名前空間を確認する必要があります。ここでそれについてすべて読んでください:

基本的に、ドメインコンテキストを定義して、ADでユーザーやグループを簡単に見つけることができます。

// set up domain context -- no domain name needed, uses default domain 
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, username);

if(user != null)
{
   // do something here....     
}

新しいS.DS.AMを使用すると、ADのユーザーやグループを簡単に操作できます。

20
marc_s

上記のmarc_sの回答 に追加するには、複数のドメインを検索する必要がありました。したがって、ドメインごとに次のことを行いました。

DirectoryEntry deRoot = new DirectoryEntry("LDAP://" +"DomainName"+ "/RootDSE");
string defaultNamingContext = "LDAP://" + deRoot.Properties["defaultNamingContext"].Value.ToString();
DirectoryEntry mySearchRoot = new DirectoryEntry(defaultNamingContext);
DirectorySearcher myDirectorySearcher = new DirectorySearcher(mySearchRoot);
1
Claudio Viz

Active Directoryの接続文字列が間違っていたため、同様のエラーが発生しました(ここで指摘したような特定の場合ではなく、常に発生していました)。私はprodの代わりにcorpを使用しました。存在する場合は、組織内の別のアプリで機能するものを使用します。

0
boaz levinson

LDAP://mydomain.com:389という形式のバインド文字列を使用できます。 LDAP:// DC = mydomain、DC = comの形式を使用しようとすると、「アクセスが拒否されました」というメッセージが表示され続けました。 LDAP://mydomain.com:389形式に切り替え、DirectoryEntryを作成するときにAuthenticationTypes.ServerBindフラグを使用してバインドすると、うまく機能しました。これはAzure App Serviceにありました。

0
r590