我正在尝试根据提供的用户名和密码对本地用户进行身份验证。我遇到了这个帖子:Validate a username and password against Active Directory?
以下是我验证用户的方式:
PrincipalContext pc = new PrincipalContext(ContextType.Machine);
bool isValid = pc.ValidateCredentials(user, pass);
只要我在网络上,它就可以正常工作,但如果我断开电脑,它就会给我:
找不到网络路径。
我要做的就是在本地机器上验证,这可能是也可能不是网络的一部分。
编辑:UserPrincipal.FindByIdentity似乎仍然没有AD,这是给我带来麻烦的pc.ValidateCredentials。答案 0 :(得分:2)
您应该查看以下链接:How to validate domain credentials?
如果您必须能够在AD不在线的情况下完成验证,那么使用LogonUser Win32 API函数似乎是唯一的选择。然而,并非没有严重的缺点(如线程中所示)。您需要使用许多权限对执行您的应用的帐户进行皮条客。
答案 1 :(得分:2)
正如您所指出的,System.DirectoryServices
命名空间在断开连接的上下文中并不是非常有用 - 您需要与LSA进行通信,而不是与其Active Directory父进行通信。
我不知道与advapi32.LogonUser
对应的官方.Net API,但您可以调用它来验证本地缓存的登录。但是,如果计算机具有网络访问权限但无法查看域控制器,则可能需要一段时间才能返回。
如果你想通过P / Invoke调用它,函数有一个declaration on pinvoke.net
。 (但我没有审核过;我发现pinvoke.net
上的签名质量差异很大。)
答案 2 :(得分:1)
可能的丑陋解决方法 -
将ValidateCredentials()与ContextType.Machine一起使用将始终首先检查本地系统的凭据。如果未在本地找到凭据,它仅执行网络活动。你可以捕获PrincipalOperationException,如果抛出并安全地忽略它,知道如果方法到目前为止,凭证无效。
答案 3 :(得分:0)
bool valid = false;
using (PrincipalContext checkpass = new PrincipalContext(ContextType.Machine)) //checks local machine first
{
try // you need to use try catch when you only have local user
{
valid = checkpass.ValidateCredentials(user, password);
}
catch (Exception ex) { valid = true; }
if (valid)
{
// returns ok
}
else
{
// returns false
}