如何对活动目录验证用户名和密码?我只是想检查用户名和密码是否正确。
当前回答
我们在内部网做这些
你必须使用System.DirectoryServices;
下面是代码的核心部分
using (DirectoryEntry adsEntry = new DirectoryEntry(path, strAccountId, strPassword))
{
using (DirectorySearcher adsSearcher = new DirectorySearcher(adsEntry))
{
//adsSearcher.Filter = "(&(objectClass=user)(objectCategory=person))";
adsSearcher.Filter = "(sAMAccountName=" + strAccountId + ")";
try
{
SearchResult adsSearchResult = adsSearcher.FindOne();
bSucceeded = true;
strAuthenticatedBy = "Active Directory";
strError = "User has been authenticated by Active Directory.";
}
catch (Exception ex)
{
// Failed to authenticate. Most likely it is caused by unknown user
// id or bad strPassword.
strError = ex.Message;
}
finally
{
adsEntry.Close();
}
}
}
其他回答
如果你使用的是。net 3.5或更新版本,你可以使用System.DirectoryServices.AccountManagement命名空间轻松验证你的凭证:
// create a "principal context" - e.g. your domain (could be machine, too)
using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "YOURDOMAIN"))
{
// validate the credentials
bool isValid = pc.ValidateCredentials("myuser", "mypassword");
}
它简单,可靠,在你的端是100%的c#托管代码——你还能要求什么呢?: -)
在这里阅读所有内容:
在.NET Framework 3.5中管理目录安全主体 System.DirectoryServices.AccountManagement上的MSDN文档
更新:
正如在另一个SO问题(及其答案)中概述的那样,对于用户的旧密码,这个调用可能会返回True。只是要注意这种行为,如果发生这种情况不要太惊讶:-)(感谢@MikeGledhill指出这一点!)
这里介绍的几个解决方案缺乏区分错误用户/密码和需要更改的密码的能力。这可以通过以下方式来实现:
using System;
using System.DirectoryServices.Protocols;
using System.Net;
namespace ProtocolTest
{
class Program
{
static void Main(string[] args)
{
try
{
LdapConnection connection = new LdapConnection("ldap.fabrikam.com");
NetworkCredential credential = new NetworkCredential("user", "password");
connection.Credential = credential;
connection.Bind();
Console.WriteLine("logged in");
}
catch (LdapException lexc)
{
String error = lexc.ServerErrorMessage;
Console.WriteLine(lexc);
}
catch (Exception exc)
{
Console.WriteLine(exc);
}
}
}
}
如果用户密码错误,或者用户不存在,error将包含
“8009030C: LdapErr: DSID-0C0904DC,注释:AcceptSecurityContext错误,数据52e, v1db1”,
如果用户密码需要修改,则包含
"8009030C: LdapErr: DSID-0C0904DC,注释:AcceptSecurityContext错误,数据773,v1db1"
lexc。ServerErrorMessage数据值是Win32错误码的十六进制表示。这些是通过调用Win32 LogonUser API调用返回的相同错误代码。下面的列表总结了一些常见的十六进制和十进制值:
525 user not found (1317)
52e invalid credentials (1326)
530 not permitted to logon at this time (1328)
531 not permitted to logon at this workstation (1329)
532 password expired (1330)
533 account disabled (1331)
701 account expired (1793)
773 user must reset password (1907)
775 user account locked (1909)
完整的. net解决方案是使用来自系统的类。DirectoryServices名称空间。它们允许直接查询AD服务器。下面是一个可以做到这一点的小样本:
using (DirectoryEntry entry = new DirectoryEntry())
{
entry.Username = "here goes the username you want to validate";
entry.Password = "here goes the password";
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "(objectclass=user)";
try
{
searcher.FindOne();
}
catch (COMException ex)
{
if (ex.ErrorCode == -2147023570)
{
// Login or password is incorrect
}
}
}
// FindOne() didn't throw, the credentials are correct
这段代码使用提供的凭据直接连接到AD服务器。如果凭证无效,则search . findone()将抛出异常。ErrorCode是一个对应于“无效的用户名/密码”COM错误。
您不需要以AD用户的身份运行代码。事实上,我成功地使用它在AD服务器上查询信息,从域外的客户端!
可能最简单的方法是PInvoke LogonUser Win32 api。
http://www.pinvoke.net/default.aspx/advapi32/LogonUser.html
MSDN参考在这里…
http://msdn.microsoft.com/en-us/library/aa378184.aspx
绝对要使用登录类型
LOGON32_LOGON_NETWORK (3)
这只创建了一个轻量级的令牌-完美的认证检查。(其他类型可用于构建交互式会话等)
试试这段代码 (注意:报告不能在windows server 2000上工作)
#region NTLogonUser
#region Direct OS LogonUser Code
[DllImport( "advapi32.dll")]
private static extern bool LogonUser(String lpszUsername,
String lpszDomain, String lpszPassword, int dwLogonType,
int dwLogonProvider, out int phToken);
[DllImport("Kernel32.dll")]
private static extern int GetLastError();
public static bool LogOnXP(String sDomain, String sUser, String sPassword)
{
int token1, ret;
int attmpts = 0;
bool LoggedOn = false;
while (!LoggedOn && attmpts < 2)
{
LoggedOn= LogonUser(sUser, sDomain, sPassword, 3, 0, out token1);
if (LoggedOn) return (true);
else
{
switch (ret = GetLastError())
{
case (126): ;
if (attmpts++ > 2)
throw new LogonException(
"Specified module could not be found. error code: " +
ret.ToString());
break;
case (1314):
throw new LogonException(
"Specified module could not be found. error code: " +
ret.ToString());
case (1326):
// edited out based on comment
// throw new LogonException(
// "Unknown user name or bad password.");
return false;
default:
throw new LogonException(
"Unexpected Logon Failure. Contact Administrator");
}
}
}
return(false);
}
#endregion Direct Logon Code
#endregion NTLogonUser
除非你需要为“LogonException”创建自己的自定义异常