.NET 4.5アプリケーションを.NET 4.5でテストすると、メソッドの問題がUserPrincipal
に発生しました。次のコードは、.NET 4.0ランタイムで実行したときに動作しますが、.NET 4.5の下で失敗します。ここでは.NET 4.5 UserPrincipal.FindByIdentity(System.DirectoryServices.AccountManagement)のバグ
[Test]
public void TestIsAccountLockedOut()
{
const string activeDirectoryServer = "MyActiveDirectoryServer";
const string activeDirectoryLogin = "[email protected]";
const string activeDirectoryPassword = "MyADAccountPassword";
const string userAccountToTest = "[email protected]";
const string userPasswordToTest = "WRONGPASSWORD";
var principalContext = new PrincipalContext(ContextType.Domain, activeDirectoryServer, activeDirectoryLogin, activeDirectoryPassword);
var isAccountLockedOut = false;
var isAuthenticated = principalContext.ValidateCredentials(userAccountToTest, userPasswordToTest, principalContext.Options);
if (!isAuthenticated)
{
// System.DirectoryServices.AccountManagement.PrincipalOperationException : Information about the domain could not be retrieved (1355).
using (var user = UserPrincipal.FindByIdentity(principalContext, IdentityType.UserPrincipalName, userAccountToTest))
{
isAccountLockedOut = (user != null) && user.IsAccountLockedOut();
}
}
Assert.False(isAuthenticated);
Assert.False(isAccountLockedOut);
}
は、例外スタックトレースです:
System.DirectoryServices.AccountManagement.PrincipalOperationException : Information about the domain could not be retrieved (1355).
at System.DirectoryServices.AccountManagement.Utils.GetDcName(String computerName, String domainName, String siteName, Int32 flags) at System.DirectoryServices.AccountManagement.ADStoreCtx.LoadDomainInfo() at
System.DirectoryServices.AccountManagement.ADStoreCtx.get_DnsDomainName() at System.DirectoryServices.AccountManagement.ADStoreCtx.GetAsPrincipal(Object storeObject, Object discriminant) at
System.DirectoryServices.AccountManagement.ADStoreCtx.FindPrincipalByIdentRefHelper(Type principalType, String urnScheme, String urnValue, DateTime referenceDate, Boolean useSidHistory) at
System.DirectoryServices.AccountManagement.ADStoreCtx.FindPrincipalByIdentRef(Type principalType, String urnScheme, String urnValue, DateTime referenceDate) at
System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithTypeHelper(PrincipalContext context, Type principalType, Nullable`1 identityType, String identityValue, DateTime refDate) at
System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithType(PrincipalContext context, Type principalType, IdentityType identityType, String identityValue) at
System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext context, IdentityType identityType, String identityValue)
は、誰が見て、この問題を解決しましたか?そうでない場合は、IsAccountLockedOut
のActive Directoryアカウントのステータスを確認する良い方法がありますか?
参考までに、すべてのテストマシンは同じサブネット内にあります。さまざまなドメイン機能モード(下記参照)で、Windows Server 2003、2008および2012を実行する別々のActive Directoryサーバーがあります。このコードは.NET 4.0を実行しているマシンからは動作しますが、.NET 4.5を実行しているマシンでは動作しません。私たちはからコードを実行した
3 .NETマシンは以下のとおりです。
- Windows 7の.NET 4.0
を実行している - .NET 4.5
を実行しているWindows Vistaの - のWindows Server 2012は、.NET 4.5
アクティブを実行しています私たちが試したディレクトリサーバーは、
- ADドメイン機能モードをWindows 2000ネイティブに設定した場合
- ADドメイン機能モードをWindows Server 2003に設定したWindows 2003
- ADドメイン機能モードのWindows 2008 Windowsの2012
に設定ADドメインの機能モードでWindows 2008 - Windows Server 2003で
に設定ADドメインの機能モードでのWindows 2008 - Windows 2000のネイティブ
へら
これらのActive Directoryサーバーはすべてシンプルな単一のフォレストとして構成され、クライアントマシンはドメインの一部ではありません。この動作をテストする以外の機能は使用されず、Active Directory以外は実行されません。
EDIT - 答えた皆様に2012年10月9日
感謝。以下は、問題を示すC#コマンドラインクライアントと、Active DirectoryおよびDNS構成について何も変更する必要のない短期的な回避策です。例外は、PrincipalContextのインスタンスで1回だけスローされたようです。 .NET 4.0マシン(Windows 7)と.NET 4.5マシン(Windows Vista)の出力を含めました。
using System;
using System.DirectoryServices.AccountManagement;
namespace ADBug
{
class Program
{
static void Main(string[] args)
{
const string activeDirectoryServer = "MyActiveDirectoryServer";
const string activeDirectoryLogin = "MyADAccount";
const string activeDirectoryPassword = "MyADAccountPassword";
const string validUserAccount = "[email protected]";
const string unknownUserAccount = "[email protected]";
var principalContext = new PrincipalContext(ContextType.Domain, activeDirectoryServer, activeDirectoryLogin, activeDirectoryPassword);
// .NET 4.0 - First attempt with a valid account finds the user
// .NET 4.5 - First attempt with a valid account fails with a PrincipalOperationException
TestFindByIdentity(principalContext, validUserAccount, "Valid Account - First Attempt");
// Second attempt with a valid account finds the user
TestFindByIdentity(principalContext, validUserAccount, "Valid Account - Second Attempt");
// First attempt with an unknown account does not find the user
TestFindByIdentity(principalContext, unknownUserAccount, "Unknown Account - First Attempt");
// Second attempt with an unknown account does not find the user (testing false positive)
TestFindByIdentity(principalContext, unknownUserAccount, "Unknown Account - Second Attempt");
// Subsequent attempt with a valid account still finds the user
TestFindByIdentity(principalContext, validUserAccount, "Valid Account - Third Attempt");
}
private static void TestFindByIdentity(PrincipalContext principalContext, string userAccountToTest, string message)
{
var exceptionThrown = false;
var userFound = false;
try
{
using (var user = UserPrincipal.FindByIdentity(principalContext, IdentityType.UserPrincipalName, userAccountToTest))
{
userFound = (user != null);
}
}
catch (PrincipalOperationException)
{
exceptionThrown = true;
}
Console.Out.WriteLine(message + " - Exception Thrown = {0}", exceptionThrown);
Console.Out.WriteLine(message + " - User Found = {1}", userAccountToTest, userFound);
}
}
}
.NET 4.0出力
Valid Account - First Attempt - Exception Thrown = False
Valid Account - First Attempt - User Found = True
Valid Account - Second Attempt - Exception Thrown = False
Valid Account - Second Attempt - User Found = True
Unknown Account - First Attempt - Exception Thrown = False
Unknown Account - First Attempt - User Found = False
Unknown Account - Second Attempt - Exception Thrown = False
Unknown Account - Second Attempt - User Found = False
Valid Account - Third Attempt - Exception Thrown = False
Valid Account - Third Attempt - User Found = True
.NET 4.5出力
Valid Account - First Attempt - Exception Thrown = True
Valid Account - First Attempt - User Found = False
Valid Account - Second Attempt - Exception Thrown = False
Valid Account - Second Attempt - User Found = True
Unknown Account - First Attempt - Exception Thrown = False
Unknown Account - First Attempt - User Found = False
Unknown Account - Second Attempt - Exception Thrown = False
Unknown Account - Second Attempt - User Found = False
Valid Account - Third Attempt - Exception Thrown = False
Valid Account - Third Attempt - User Found = True
あなたがこれをまだGoogleで検索しているかどうかはわかりませんが、さまざまなシーンの修正に関するコメントがある投稿がありますこれが原因かもしれない:http://elegantcode.com/2009/03/21/one-scenario-where-the- systemdirectoryservices-accountmanagement-api-falls-down/私はそれを自分で見たことがないが、興味のある役に立ったと思ったので、私はこのことを分かりやすいと思った。 – David
たとえば、DCとCNで渡してみましたか? PrincipalContext ctx =新しいPrincipalContext( ContextType.Domain、 "fabrikam.com"、 "CN =ユーザー、DC = fabrikam、DC = com"、 "administrator" 、 "securelyStoredPassword"); – MethodMan
DJ、CN&DC文字列を渡してみましたが、それでも.NET 4.0では動作し、.NET 4.5では失敗します。 –