Windows Vista Ultimate SP1で次のコードを使用してActive Directoryサーバーにクエリを実行し、ドメイン上のユーザーのユーザー名とパスワードを確認しています。
public Object IsAuthenticated()
{
String domainAndUsername = strDomain + "\\" + strUser;
DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, strPass);
SearchResult result;
try
{
//Bind to the native AdsObject to force authentication.
DirectorySearcher search = new DirectorySearcher(entry) { Filter = ("(SAMAccountName=" + strUser + ")") };
search.PropertiesToLoad.Add("givenName"); // First Name
search.PropertiesToLoad.Add("sn"); // Last Name
search.PropertiesToLoad.Add("cn"); // Last Name
result = search.FindOne();
if (null == result)
{
return null;
}
//Update the new path to the user in the directory.
_path = result.Path;
_filterAttribute = (String)result.Properties["cn"][0];
}
catch (Exception ex)
{
return new Exception("Error authenticating user. " + ex.Message);
}
return user;
}
ターゲットは.NET 3.5を使用しており、VS 2008標準でコンパイルされています
アプリケーションが実行されているドメイン管理者であるドメインアカウントでログインしています。
コードはWindows XPで完全に機能します。しかし、Vistaで実行すると次の例外が発生します。
System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password.
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_AdsObject()
at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
at System.DirectoryServices.DirectorySearcher.FindOne()
at Chain_Of_Custody.Classes.Authentication.LdapAuthentication.IsAuthenticated()
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_AdsObject()
at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
at System.DirectoryServices.DirectorySearcher.FindOne()
at Chain_Of_Custody.Classes.Authentication.LdapAuthentication.IsAuthenticated()
認証タイプを変更しようとしましたが、何が起こっているのかわかりません。
こちらもご覧ください: Active Directoryに対してユーザー名とパスワードを検証しますか?
.net 3.5を使用している場合は、代わりにこのコードを使用してください。
ユーザーを認証するには:
PrincipalContext adContext = new PrincipalContext(ContextType.Domain);
using (adContext)
{
return adContext.ValidateCredentials(UserName, Password);
}
オブジェクトのR/W属性に対するユーザーを見つける必要がある場合は、次のようにします。
PrincipalContext context = new PrincipalContext(ContextType.Domain);
UserPrincipal foundUser =
UserPrincipal.FindByIdentity(context, "jdoe");
これはSystem.DirectoryServices.AccountManagement名前空間を使用しているため、usingステートメントに追加する必要があります。
レガシコードを使用するためにUserPrincipalオブジェクトをDirectoryEntryオブジェクトに変換する必要がある場合は、次の操作を実行できます。
DirectoryEntry userDE = (DirectoryEntry)foundUser.GetUnderlyingObject();
同じコードが複数のWebサイトでインターネット上に浮かんでいることがわかりましたが、うまくいきませんでした。 Steve Evansは、おそらく.NET 3.5を使用している場合は、このコードを使用しないでください。ただし、まだ.NET 2.0を使用している場合は、これを試してADサービスの認証を行うことができます。
DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain,
userName, password,
AuthenticationTypes.Secure | AuthenticationTypes.SecureSocketsLayer);
object nativeObject = entry.NativeObject;
最初の行は、ドメイン、ユーザー名、およびパスワードを使用してDirectoryEntryオブジェクトを作成します。また、AuthenticationTypesも設定します。 2つのパラメーター間で「ビットごとのOR」(「|」)演算子を使用して、セキュア(Kerberos)認証とSSLの両方を設定していることに注目してください。
2行目は、1行目の情報を使用して、「entry」のNativeObjectをADサービスに強制的にバインドします。
例外がスローされた場合、資格情報(または設定)が不良でした。例外がなければ、認証されています。例外メッセージは通常、何が問題なのかを示します。
このコードは既にあるものとかなり似ていますが、「パス」がある場所でドメインが使用され、ユーザー名はドメインと結合されません。 AuthenticationTypesも適切に設定してください。これにより、認証機能が有効または無効になります。
とにかく私はそれを考え出しましたVistaのユーザー名でドメインを渡すと「domain\user」のように機能しないので、「user」を渡すだけで問題なく動作するようです-同じドメインにいる必要があります
LDAPへのバインドには、昇格された特権(UAC)が必要ですか? Visual Studioやアプリを管理者として実行してみて、それが役立つかどうかを確認できます。それが問題である場合は、常にアプリケーションにマニフェストを追加し、昇格を要求するように設定することができます。そうすることで、ユーザーが実行するときにプロンプトが表示されます。
なぜ昇格した特権が必要になるのかはわかりませんが、一見の価値があります。