PrimaryContext.ValidateCredentials 始终返回 FALSE

发布于 2024-08-23 15:43:36 字数 806 浏览 12 评论 0原文

我有一个 MVC 应用程序,需要登录并根据 Active Directory 验证用户。我正在使用 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;
}

有人知道为什么会发生这种情况吗?

I have an MVC application that needs to login and verify a user against Active Directory. I am using the PrincipalContext.ValidateCredentials method but always get a authentication of false.

Connecting to the Server is fine. The problem seems to occur in the ValidateCredentials.

Here is my code:

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;
}

Anyone know why this would be happening?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

や莫失莫忘 2024-08-30 15:43:36

ValidateCredentials(string, string) 的工作原理如下:首先,它尝试使用 NegotiateSigningSealing 进行身份验证代码>上下文选项。如果失败,它会使用 SimpleBindSecureSocketLayer 再次尝试。

问题在于 NT4(又名“旧版”、又名“下级名称”)格式(DOMAIN\UserName,或更准确地说,NetBiosName\SamAccountName)不'不与谈判一起工作。但它确实可以与 SimpleBind 一起使用。

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

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

正如其中一条评论中提到的,您永远永远不想单独使用 SimpleBind (没有 SecureSocketLayer),否则您的密码将以纯文本形式通过网络发送。

在野外,我发现某些 Active Directory 系统根本不允许使用简单绑定,因此您必须使其与 Negotiate 一起使用。

我找到了 2 种方法来处理这个问题:

1) 如果所有事情都发生在同一个域上,您应该能够仅使用用户名(SAM 帐户名)调用 ValidateCredentials,而忽略“域”部分。然后,第一次使用 Negotiate 就可以正常工作了。

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

Here's how ValidateCredentials(string, string) works: First, it tries to authenticate with the Negotiate, Signing, and Sealing context options. If this fails, it tries again with SimpleBind and SecureSocketLayer.

The problem is that the NT4 (AKA "legacy", AKA "down-level name") format (DOMAIN\UserName, or more correctly, NetBiosName\SamAccountName) doesn't work with Negotiate. But it does work with SimpleBind.

So what's probably happening when calling the 2-parameter ValidateCredentials() method, is that it first fails using Negotiate because it doesn't like the NT4 format, and then fails again when using simple bind.

During my own testing, I've found that the reason why it fails even after falling back to using simple bind is that it's not only using SimpleBind. It's using SimpleBind plus SecureSocketLayer. This means that it will still fail if the Active Directory server isn't set up correctly to use SSL (a common scenario for test environments).

As was mentioned in one of the comments, you NEVER, NEVER want to use SimpleBind by itself (without SecureSocketLayer), otherwise your passwords are sent over the network in plain text.

In the wild, I've seen that some Active Directory systems don't allow the use of simple binds at all, so you must make it work with Negotiate.

I've found 2 ways to deal with this problem:

1) If everything is happening on the same domain, you should be able to call ValidateCredentials with only the username (SAM account name), leaving out the "DOMAIN\" part. Then, it will work properly the first time with Negotiate.

2) If the domain part is important because there may be multiple domains involved (i.e. Domain1\UserA and Domain2\UserA are different people), then it gets a bit more complicated. In this case what I ended up doing was translating the NT4 name (DOMAIN\User) to "user principal name" format (e.g. [email protected]). There are a couple different ways to do this. The easiest is probably to use the 3-parameter overload of UserPrincipal.FindByIdentity(), and then grab the value of the UserPrincipalName property on the result. Another way would be to use a DirectorySearcher and query LDAP://domain for the userPrincipalName property of the user with the matching sAMAccountName value. Note: this solution will only work if all the domains involved are in the same forest.

晒暮凉 2024-08-30 15:43:36

我不知道你在哪里初始化“pwd”变量
也许您应该在此方法中使用 ContextOption 来准确指定所需的行为。抱歉,您的回答太宽泛,但您的问题中没有太多细节

I don't see where you initializes the "pwd" variable
Maybe you should use ContextOption in this method to specify exactly the reqired behaviour. Sorry for too broad response but there is no much details in your question

剩余の解释 2024-08-30 15:43:36

您似乎正在使用域\用户名格式验证用户。您可能想要从 userName 解析域名并使用 ValidateCredential。

It seems you are validating the user with domain\userName format. You might want to parse the domain name from userName and user the ValidateCredential.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文