PrincipalContext.ValidateCredentials始终返回FALSE
我有一个MVC应用程序,需要登录并根据Active Directory验证用户。我正在使用PrincipalContext.ValidateCredentials
方法,但始终得到false
的身份验证。PrincipalContext.ValidateCredentials始终返回FALSE
连接到服务器没问题。该问题似乎发生在ValidateCredentials
。
这里是我的代码:
public static bool IsAuthenticated(string domain, string username, string pwd) {
bool IsAuthenticated = false;
try {
PrincipalContext insPrincipalContext =
new PrincipalContext(ContextType.Domain, domain, "DC=c1w,DC=com");
username = "c1w\\" + username;
IsAuthenticated = insPrincipalContext.ValidateCredentials(username, pwd);
}
catch (Exception ex)
{
// Rethrow this exception
ExceptionPolicy.HandleException(ex, "Exception Policy");
}
return IsAuthenticated;
}
任何人都知道为什么会发生?
看来你正在验证与域\用户名格式的用户。您可能想要从userName解析域名并使用ValidateCredential。
以下是ValidateCredentials(string, string)
的工作原理:首先,它会尝试使用Negotiate
,Signing
和Sealing
上下文选项进行验证。如果失败,则会再次尝试SimpleBind
和SecureSocketLayer
。
问题是NT4(AKA“legacy”,又名“down-level name”)格式(DOMAIN\UserName
,或更正确的NetBiosName\SamAccountName
)不适用于Negotiate。但它与SimpleBind一起工作。
因此调用双参数ValidateCredentials()
方法时可能发生的事情是,它首先使用Negotiate失败,因为它不喜欢NT4格式,然后在使用简单绑定时再次失败。
在我自己的测试过程中,我发现即使在使用简单绑定后它失败的原因是它不仅使用SimpleBind。它使用SimpleBind
加SecureSocketLayer
。这意味着如果Active Directory服务器未正确设置为使用SSL(测试环境的常见场景),它仍会失败。
正如其中一条评论中提到的,您永远不会自己使用SimpleBind
(没有SecureSocketLayer
),否则您的密码将通过网络以纯文本形式发送。
在野外,我已经看到一些Active Directory系统根本不允许使用简单的绑定,所以您必须使其与Negotiate协同工作。
我发现2种方式来处理这个问题:
1)如果一切都在同一个域发生的事情,你应该能够调用ValidateCredentials
只用用户名(SAM帐户名),留出“DOMAIN \”部分。然后,它会在第一次协商时正常工作。 2)如果域部分很重要,因为可能涉及多个域(即Domain1\UserA
和Domain2\UserA
是不同的人),那么它会变得更复杂一些。在这种情况下,我最终做的是将NT4名称(DOMAIN \ User)转换为“用户主体名称”格式(例如[email protected]
)。有几种不同的方式来做到这一点。最简单的可能是使用UserPrincipal.FindByIdentity()
的3参数超载,然后抓取结果上UserPrincipalName
属性的值。另一种方式是使用DirectorySearcher
并且查询LDAP://domain
来获得具有匹配的sAMAccountName
值的用户的userPrincipalName
属性。注意:只有涉及的所有域位于同一个林中时,此解决方案才会起作用。
编辑该问题以包含整个方法。将尝试ContextOption建议。谢谢。 – 2010-03-02 14:27:04
B-Rain, ContextOption参考指出我正确的方向。在我对AD和ContextOptions.SimpleBind的验证凭证调用上使用ContextOptions.Negotiate结束。简单的绑定将为我工作,因为该网站将SSL安全。 感谢您的帮助。 – 2010-03-02 15:30:19
Upvoted这个问题和答案,因为这也帮助我在我的情况。在我的情况下,我的开发机器(登录工作时没有指定上下文)位于网络上的安全区域,但Web服务器(登录在没有指定上下文的情况下无法工作)位于DMZ中。我使用与@Billy Logan相同的配置 - 在validate调用上协商AD和SimpleBind的调用。 – arootbeer 2010-10-14 19:52:03