已经有a few questions询问如何验证Active Directory域问题。但是,我不认为他们在森林中充分利用了多域方案。首先,他们都建议在使用.NET 3.5+的C#中执行AD身份验证的最明确方式应该是这样的:
bool isValid = false;
using(var ctx = new PrincipalContext(ContextType.Domain, "foo.com"))
{
// verify user exists first
var lookedUp = UserPrincipal.FindByIdentity(ctx, "myuser");
if (lookedUp != null)
{
// validate credentials
isValid = pc.ValidateCredentials("myuser", "mypassword");
}
}
当您要进行身份验证的用户属于foo.com时,这一切都很顺利。但是,在属于子域的用户的情况下存在一些微妙的意外差异,其子密码也已过期。 (我已经成功地让PrincipalContext
以两种不同的方式在子域中查找用户:(a)将域参数设置为"foo.com:3268"
;(b)添加容器参数w /基本DN子域:new PrincipalContext(ContextType.Domain, "foo.com", "dc=child,dc=foo,dc=com")
。我在下面描述的问题出现在两种情况中。)
如果用户属于foo.com,并且密码已过期,ValidateCredentials
会返回true
(至少在我正在测试的Windows 7上;我看到其他人说这个行为是在Windows 2003中有所不同)。但是,如果用户属于child.foo.com且密码已过期,则ValidateCredentials
会返回false
。
能够区分“有效密码但已过期”和“无效密码”对我来说非常重要。如果输入的密码正确但已过期,那么我希望能够将它们重定向到“更改密码”屏幕。但是,如果他们输入的密码完全错误,则可以将其视为信息泄漏,以将其转发到更改密码屏幕。
我看到的唯一前进方法是使用LDAP接口到AD并尝试解析它发回的状态消息以找出底层错误代码。这听起来既不好玩也不明智。
在处理同一个林中的子域时,任何人都可以提供此行为的原因吗?任何人都可以提供我想在这里完成的解决方案吗?
答案 0 :(得分:1)
所以看来这里的问题是.NET最终会尝试做一个叫做快速并发LDAP绑定到AD的东西。这是一个超级轻量级的机制,谷歌似乎表明它可能会绕过到期检查。我没有验证这一点,但是,假设它是真的......
我认为你的选择是a)自己做绑定(查看LDAPConnection类和相关的标志)或b)P / Invoke LogonUser。如果呼叫失败,您可能需要深入了解密码到期状态,因为我不确定其中任何一个是否会告诉您它已过期或未作为原因失败。