如何对活动目录验证用户名和密码?我只是想检查用户名和密码是否正确。
当前回答
对我来说,这两个下面的工作,确保你的域名是LDAP://在开始
//"LDAP://" + domainName
private void btnValidate_Click(object sender, RoutedEventArgs e)
{
try
{
DirectoryEntry de = new DirectoryEntry(txtDomainName.Text, txtUsername.Text, txtPassword.Text);
DirectorySearcher dsearch = new DirectorySearcher(de);
SearchResult results = null;
results = dsearch.FindOne();
MessageBox.Show("Validation Success.");
}
catch (LdapException ex)
{
MessageBox.Show($"Validation Failure. {ex.GetBaseException().Message}");
}
catch (Exception ex)
{
MessageBox.Show($"Validation Failure. {ex.GetBaseException().Message}");
}
}
private void btnValidate2_Click(object sender, RoutedEventArgs e)
{
try
{
LdapConnection lcon = new LdapConnection(new LdapDirectoryIdentifier((string)null, false, false));
NetworkCredential nc = new NetworkCredential(txtUsername.Text,
txtPassword.Text, txtDomainName.Text);
lcon.Credential = nc;
lcon.AuthType = AuthType.Negotiate;
lcon.Bind(nc);
MessageBox.Show("Validation Success.");
}
catch (LdapException ex)
{
MessageBox.Show($"Validation Failure. {ex.GetBaseException().Message}");
}
catch (Exception ex)
{
MessageBox.Show($"Validation Failure. {ex.GetBaseException().Message}");
}
}
其他回答
另一个.NET调用用于快速验证LDAP凭据:
using System.DirectoryServices;
using(var DE = new DirectoryEntry(path, username, password)
{
try
{
DE.RefreshCache(); // This will force credentials validation
}
catch (COMException ex)
{
// Validation failed - handle how you want
}
}
Windows身份验证失败的原因有很多:用户名或密码不正确、帐户被锁定、密码过期等等。为了区分这些错误,通过P/Invoke调用LogonUser API函数,如果函数返回false,检查错误代码:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
public static class Win32Authentication
{
private class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle() // called by P/Invoke
: base(true)
{
}
protected override bool ReleaseHandle()
{
return CloseHandle(this.handle);
}
}
private enum LogonType : uint
{
Network = 3, // LOGON32_LOGON_NETWORK
}
private enum LogonProvider : uint
{
WinNT50 = 3, // LOGON32_PROVIDER_WINNT50
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(
string userName, string domain, string password,
LogonType logonType, LogonProvider logonProvider,
out SafeTokenHandle token);
public static void AuthenticateUser(string userName, string password)
{
string domain = null;
string[] parts = userName.Split('\\');
if (parts.Length == 2)
{
domain = parts[0];
userName = parts[1];
}
SafeTokenHandle token;
if (LogonUser(userName, domain, password, LogonType.Network, LogonProvider.WinNT50, out token))
token.Dispose();
else
throw new Win32Exception(); // calls Marshal.GetLastWin32Error()
}
}
示例用法:
try
{
Win32Authentication.AuthenticateUser("EXAMPLE\\user", "P@ssw0rd");
// Or: Win32Authentication.AuthenticateUser("user@example.com", "P@ssw0rd");
}
catch (Win32Exception ex)
{
switch (ex.NativeErrorCode)
{
case 1326: // ERROR_LOGON_FAILURE (incorrect user name or password)
// ...
case 1327: // ERROR_ACCOUNT_RESTRICTION
// ...
case 1330: // ERROR_PASSWORD_EXPIRED
// ...
case 1331: // ERROR_ACCOUNT_DISABLED
// ...
case 1907: // ERROR_PASSWORD_MUST_CHANGE
// ...
case 1909: // ERROR_ACCOUNT_LOCKED_OUT
// ...
default: // Other
break;
}
}
注意:LogonUser需要与您验证的域建立信任关系。
对我来说,这两个下面的工作,确保你的域名是LDAP://在开始
//"LDAP://" + domainName
private void btnValidate_Click(object sender, RoutedEventArgs e)
{
try
{
DirectoryEntry de = new DirectoryEntry(txtDomainName.Text, txtUsername.Text, txtPassword.Text);
DirectorySearcher dsearch = new DirectorySearcher(de);
SearchResult results = null;
results = dsearch.FindOne();
MessageBox.Show("Validation Success.");
}
catch (LdapException ex)
{
MessageBox.Show($"Validation Failure. {ex.GetBaseException().Message}");
}
catch (Exception ex)
{
MessageBox.Show($"Validation Failure. {ex.GetBaseException().Message}");
}
}
private void btnValidate2_Click(object sender, RoutedEventArgs e)
{
try
{
LdapConnection lcon = new LdapConnection(new LdapDirectoryIdentifier((string)null, false, false));
NetworkCredential nc = new NetworkCredential(txtUsername.Text,
txtPassword.Text, txtDomainName.Text);
lcon.Credential = nc;
lcon.AuthType = AuthType.Negotiate;
lcon.Bind(nc);
MessageBox.Show("Validation Success.");
}
catch (LdapException ex)
{
MessageBox.Show($"Validation Failure. {ex.GetBaseException().Message}");
}
catch (Exception ex)
{
MessageBox.Show($"Validation Failure. {ex.GetBaseException().Message}");
}
}
如果你被。net 2.0和托管代码困住了,这里有另一种处理本地和域帐户的方法:
using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Diagnostics;
static public bool Validate(string domain, string username, string password)
{
try
{
Process proc = new Process();
proc.StartInfo = new ProcessStartInfo()
{
FileName = "no_matter.xyz",
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
RedirectStandardInput = true,
LoadUserProfile = true,
Domain = String.IsNullOrEmpty(domain) ? "" : domain,
UserName = username,
Password = Credentials.ToSecureString(password)
};
proc.Start();
proc.WaitForExit();
}
catch (System.ComponentModel.Win32Exception ex)
{
switch (ex.NativeErrorCode)
{
case 1326: return false;
case 2: return true;
default: throw ex;
}
}
catch (Exception ex)
{
throw ex;
}
return false;
}
如果你使用的是。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指出这一点!)
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 如何使用JSON确保字符串是有效的JSON。网
- AppSettings从.config文件中获取值
- 通过HttpClient向REST API发布一个空体
- 如何检查IEnumerable是否为空或空?
- 自动化invokerrequired代码模式
- 在c#代码中设置WPF文本框的背景颜色
- 在c#中,什么是单子?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- c#线程安全快速(est)计数器
- 如何将此foreach代码转换为Parallel.ForEach?
- 如何分裂()一个分隔字符串到一个列表<字符串>
- 如何转换列表<字符串>列表<int>?
- c#对象列表,我如何得到一个属性的和