PrimaryContext.ValidateCredentials 始终返回 FALSE
我有一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
ValidateCredentials(string, string)
的工作原理如下:首先,它尝试使用Negotiate
、Signing
和Sealing
进行身份验证代码>上下文选项。如果失败,它会使用SimpleBind
和SecureSocketLayer
再次尝试。问题在于 NT4(又名“旧版”、又名“下级名称”)格式(
DOMAIN\UserName
,或更准确地说,NetBiosName\SamAccountName
)不'不与谈判一起工作。但它确实可以与 SimpleBind 一起使用。因此,在调用 2 参数 ValidateCredentials() 方法时可能会发生的情况是,它首先使用 Negotiate 失败,因为它不喜欢 NT4 格式,然后在使用简单绑定时再次失败。
在我自己的测试中,我发现即使在回退到使用简单绑定后它仍然失败的原因是它不仅使用 SimpleBind。它使用
SimpleBind
和SecureSocketLayer
。这意味着如果 Active Directory 服务器未正确设置为使用 SSL(测试环境的常见情况),它仍然会失败。正如其中一条评论中提到的,您永远永远不想单独使用
SimpleBind
(没有SecureSocketLayer
),否则您的密码将以纯文本形式通过网络发送。在野外,我发现某些 Active Directory 系统根本不允许使用简单绑定,因此您必须使其与 Negotiate 一起使用。
我找到了 2 种方法来处理这个问题:
1) 如果所有事情都发生在同一个域上,您应该能够仅使用用户名(SAM 帐户名)调用 ValidateCredentials,而忽略“域”部分。然后,第一次使用 Negotiate 就可以正常工作了。
2) 如果域部分很重要,因为可能涉及多个域(即
Domain1\UserA
和Domain2\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 theNegotiate
,Signing
, andSealing
context options. If this fails, it tries again withSimpleBind
andSecureSocketLayer
.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
plusSecureSocketLayer
. 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 (withoutSecureSocketLayer
), 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
andDomain2\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 ofUserPrincipal.FindByIdentity()
, and then grab the value of theUserPrincipalName
property on the result. Another way would be to use aDirectorySearcher
and queryLDAP://domain
for theuserPrincipalName
property of the user with the matchingsAMAccountName
value. Note: this solution will only work if all the domains involved are in the same forest.我不知道你在哪里初始化“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
您似乎正在使用域\用户名格式验证用户。您可能想要从 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.