C# UserPrincipal.FindByIdentity(System.DirectoryServices.AccountManagement)中的.NET 4.5错误

C# UserPrincipal.FindByIdentity(System.DirectoryServices.AccountManagement)中的.NET 4.5错误,c#,.net,authentication,active-directory,.net-4.5,C#,.net,Authentication,Active Directory,.net 4.5,在.NET 4.5下测试.NET 4.0应用程序时,我们遇到了UserPrincipal的FindByIdentity方法的问题。以下代码在.NET 4.0运行时运行时有效,但在.NET 4.5下失败: [Test] public void TestIsAccountLockedOut() { const string activeDirectoryServer = "MyActiveDirectoryServer"; const string activeDirectoryLo

在.NET 4.5下测试.NET 4.0应用程序时,我们遇到了
UserPrincipal
FindByIdentity
方法的问题。以下代码在.NET 4.0运行时运行时有效,但在.NET 4.5下失败:

[Test]
public void TestIsAccountLockedOut()
{
    const string activeDirectoryServer = "MyActiveDirectoryServer";
    const string activeDirectoryLogin = "MyADAccount@MyDomain";
    const string activeDirectoryPassword = "MyADAccountPassword";
    const string userAccountToTest = "TestUser@MyDomain";
    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)   
还有其他人看到并解决了这个问题吗?如果没有,是否有更好的方法检查Active Directory帐户的
IsAccountLockedOut
状态

作为参考,我们所有的测试机器都在同一个子网内。有单独的ActiveDirectory服务器以各种域功能模式运行Windows Server 2003、2008和2012(见下文)。代码在运行.NET4.0的机器上运行,但在运行.NET4.5的机器上失败

我们运行代码的三台.NET计算机是:
-运行.NET 4.0的Windows 7
-运行.NET 4.5的Windows Vista
-运行.NET 4.5的Windows Server 2012

我们尝试的Active Directory服务器是:
-Windows 2003,AD域功能模式设置为Windows 2000本机
-将AD域功能模式设置为Windows Server 2003的Windows 2003
-Windows 2008,AD域功能模式设置为Windows 2000本机
-Windows 2008将AD域功能模式设置为Windows Server 2003
-Windows 2008将AD域功能模式设置为Windows Server 2008
-Windows 2012,AD域功能模式设置为Windows 2012

所有这些Active Directory服务器都配置为简单的单林,并且客户端计算机不是域的一部分。它们不用于测试此行为以外的任何其他功能,也不运行除Active Directory之外的任何其他功能


编辑日期:2012年10月9日

感谢所有回复的人。下面是一个C#命令行客户端,它演示了这个问题,以及我们确定的一个短期解决方案,它不需要我们更改任何有关Active Directory和DNS配置的内容。对于PrincipalContext的实例,异常似乎只抛出一次。我们包括了.NET4.0机器(Windows7)和.NET4.5机器(WindowsVista)的输出

.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

我们遇到完全相同的问题(跨域查询失败,更新到4.5)-我会认为这是一个错误,因为它打破现有的(4)代码。 然而,为了让它发挥作用——看看一个(现在)失败的客户机,我注意到有一堆针对SRV记录的DNS请求失败,其形式如下:

_ldap._tcp.MYSERVER1.mydomain.com,INet,Srv
_ldap._tcp.dc._msdcs.mydomain.com,INet,Srv
修改我们的DNS服务器(失败的客户端使用的DNS),使所有mydomain.com流量都有一个转发区域,可以转发到域上的一个DC,这确实解决了问题

使用nslookup,从以前(失败时)到现在(工作时)的行为是,在这些查询之前,它们将返回“不存在的域”,而现在它们返回“*没有可用于…”的服务位置(SRV)记录。故障点似乎是认为域不存在,而不是缺少SRV记录。希望MS能恢复此行为,但与此同时,如果您能控制失败客户端的DNS,您可能会有幸创建DNS转发区域。

对于OP(以及帮助回复的任何其他人),我们也有同样的问题。在我们的开发环境中,安装的VS2012和我们的应用程序在登录时在运行时中断(上面指出的广告问题)。所以我把我的系统擦掉,继续使用2010,每次我读到一篇关于2012是多么棒的博文时,我都会流泪

多亏了斯科特·汉塞尔曼,我找到了这条线索。我在我的开发盒上安装了一个VM,在上面安装了Windows8Developer90Day预览版,以及VS2012。我们的应用程序启动并运行后,立即遇到登录广告障碍。简单地将我们的FindByIdentity包装在一个try-catch中,并强迫它在第一个catch之后再试一次——viola成功了!!多亏了想出这个小把戏的人

因此,这只是一个小补丁,是一个“黑客”行为,对本地开发有效,不应该影响生产,因为我们不会很快将4.5投入生产

但缺点是,在本地,登录现在需要2分钟,而在2010年下运行时需要2秒:(


我真的不知道我还能提供什么来帮助解决这个问题,但我想我还是会分享我的2美分,因为这似乎仍然是一个主要问题。

在将.net framework从4.0升级到4.5之后也遇到了同样的问题
我已经将框架升级到.net 4.5.1,它已经运行了。

不确定你是否已经在谷歌上搜索过了,但是我发现了一篇帖子,其中有一些关于可能导致这种情况的修复方法的评论:我自己从未见过它,但是为了对大家有所帮助,我想分享一下,因为它对我来说很有用。例如,你有没有试着通过DC和CN,例如PrincipalContext ctx=新PrincipalContext(ContextType.Domain,“fabrikam.com”,“CN=用户,DC=fabrikam,DC=com”,“管理员”,“安全存储密码”);DJ,我们刚刚尝试传入CN&DC字符串,但它在.NET 4.0下仍然有效,在.NET 4.5下失败。我只是想确认您不是唯一有此问题的人。我有一段几乎相同的代码,在FindByIdentity上引发了相同的异常。我在三台具有相同网络设置的计算机上运行了它,等等使用.NET 4.5的版本失败了。我不能很快地将错误声明为外部错误,但它在升级之前确实有效。我还确认了此问题。使用vmware快照来恢复.NET 4.5安装之前/之后的系统,以验证问题是何时开始的。我们还从不在域中的计算机上查询
_ldap._tcp.MYSERVER1.mydomain.com,INet,Srv
_ldap._tcp.dc._msdcs.mydomain.com,INet,Srv