PrincipalContext.ValidateCredentials始终返回FALSE

我有一个MVC应用程序需要登录并validation用户对Active Directory。 我正在使用PrincipalContext.ValidateCredentials方法,但总是获得false的身份validation。

连接到服务器很好。 问题似乎发生在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; } 

任何人都知道为什么会发生这种情况?

我没有看到你在哪里初始化“pwd”变量也许你应该在这个方法中使用ContextOption来准确指定所需的行为。 很抱歉,回复过于宽泛,但您的问题中没有太多详细信息

以下是ValidateCredentials(string, string)工作原理:首先,它尝试使用NegotiateSigningSealing上下文选项进行身份validation。 如果失败,它将再次尝试使用SimpleBindSecureSocketLayer

问题是NT4(AKA“遗留”,AKA“低级名称”)格式( DOMAIN\UserName ,或更准确地说, NetBiosName\SamAccountName )不适用于Negotiate。 但它确实适用于SimpleBind。

因此,在调用2参数ValidateCredentials()方法时可能发生的情况是,它首先使用Negotiate失败,因为它不喜欢NT4格式,然后在使用简单绑定时再次失败。

在我自己的测试中,我发现即使在回归使用简单绑定之后它失败的原因是它不仅使用SimpleBind。 它使用的是SimpleBindSecureSocketLayer 。 这意味着如果未正确设置Active Directory服务器以使用SSL(测试环境的常见方案),它仍将失败。

正如其中一条评论中所提到的,你永远不要自己使用SimpleBind (没有SecureSocketLayer ),否则你的密码将通过网络以纯文本forms发送。

在野外,我已经看到一些Active Directory系统根本不允许使用简单的绑定,所以你必须使它与Negotiate一起使用。

我找到了两种方法来解决这个问题:

1)如果所有内容都发生在同一个域上,您应该只能使用用户名(SAM帐户名称)调用ValidateCredentials ,而忽略“DOMAIN”部分。 然后,第一次与Negotiate一起正常工作。

2)如果域部分很重要,因为可能涉及多个域(即Domain1\UserADomain2\UserA是不同的人),那么它会变得有点复杂。 在这种情况下,我最终做的是将NT4名称(DOMAIN \ User)转换为“用户主体名称”格式(例如LogonName@domain.com )。 有几种不同的方法可以做到这一点。 最简单的可能是使用UserPrincipal.FindByIdentity()的3参数重载,然后在结果上获取UserPrincipalName属性的值。 另一种方法是使用DirectorySearcher并使用匹配的sAMAccountName值查询LDAP://domain以获取用户的userPrincipalName属性。 注意:此解决方案仅在涉及的所有域位于同一林中时才有效。

您似乎正在使用domain \ userName格式validation用户。 您可能希望从userName解析域名,并使用ValidateCredential。