我想对域控制器验证一组凭据。例如:
Username: STACKOVERFLOW\joel
Password: splotchy
方法1.模拟查询Active
很多人建议向Active Directory查询一些内容。如果引发异常,那么您就知道凭据无效-正如这个堆叠溢出问题中所建议的那样。
然而,有一些严重的这种方法的缺点:
方法2. LogonUser Win32 API
其他建议使用LogonUser()
API函数。这听起来不错,但不幸的是,调用用户有时需要通常只授予操作系统本身的权限:
调用LogonUser的进程需要SE_TCB_NAME特权。如果调用进程没有此特权,则LogonUser失败,GetLastError返回ERROR_PRIVILEGE_NOT_HELD。 在某些情况下,调用LogonUser的进程还必须启用SE_CHANGE_NOTIFY_NAME特权;否则,LogonUser失败,GetLastError返回ERROR_ACCESS_DENIED。对于作为管理员组成员的本地系统帐户或帐户,不需要此特权。默认情况下,对所有用户都启用了SE_CHANGE_NOTIFY_NAME,但有些管理员可能会为每个人禁用它。
授予“作为操作系统一部分的行为”特权并不像微软在知识库文章中指出的那样,你不想故意这么做。
调用...the进程的LogonUser必须具有SE_TCB_NAME特权(在用户管理器中,这是“作为操作系统一部分的行为”的权限)。SE_TCB_NAME权限非常强大,不应该将授予任何任意用户,这样他们就可以运行需要验证凭据的应用程序。
此外,如果指定了空白密码,则调用LogonUser()
将失败。
验证一组域凭据的正确方法是什么?
我碰巧是从托管代码中调用的,但这是一个一般的Windows问题。可以假定客户已经安装了.NET Framework2.0。
发布于 2008-11-29 02:41:11
C#在.NET 3.5中使用System.DirectoryServices.AccountManagement。
bool valid = false;
using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
{
valid = context.ValidateCredentials( username, password );
}
这将根据当前域进行验证。查看其他选项的参数化PrincipalContext构造函数。
发布于 2011-08-03 17:05:17
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
using System.DirectoryServices.AccountManagement;
public struct Credentials
{
public string Username;
public string Password;
}
public class Domain_Authentication
{
public Credentials Credentials;
public string Domain;
public Domain_Authentication(string Username, string Password, string SDomain)
{
Credentials.Username = Username;
Credentials.Password = Password;
Domain = SDomain;
}
public bool IsValid()
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, Domain))
{
// validate the credentials
return pc.ValidateCredentials(Credentials.Username, Credentials.Password);
}
}
}
发布于 2014-11-06 17:33:44
我正在使用以下代码来验证凭据。下面显示的方法将确认凭据是否正确,如果不正确,密码是否过期或是否需要更改。
我已经找了这么久了.所以我希望这能帮上忙!
using System;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.Runtime.InteropServices;
namespace User
{
public static class UserValidation
{
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool LogonUser(string principal, string authority, string password, LogonTypes logonType, LogonProviders logonProvider, out IntPtr token);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
enum LogonProviders : uint
{
Default = 0, // default for platform (use this!)
WinNT35, // sends smoke signals to authority
WinNT40, // uses NTLM
WinNT50 // negotiates Kerb or NTLM
}
enum LogonTypes : uint
{
Interactive = 2,
Network = 3,
Batch = 4,
Service = 5,
Unlock = 7,
NetworkCleartext = 8,
NewCredentials = 9
}
public const int ERROR_PASSWORD_MUST_CHANGE = 1907;
public const int ERROR_LOGON_FAILURE = 1326;
public const int ERROR_ACCOUNT_RESTRICTION = 1327;
public const int ERROR_ACCOUNT_DISABLED = 1331;
public const int ERROR_INVALID_LOGON_HOURS = 1328;
public const int ERROR_NO_LOGON_SERVERS = 1311;
public const int ERROR_INVALID_WORKSTATION = 1329;
public const int ERROR_ACCOUNT_LOCKED_OUT = 1909; //It gives this error if the account is locked, REGARDLESS OF WHETHER VALID CREDENTIALS WERE PROVIDED!!!
public const int ERROR_ACCOUNT_EXPIRED = 1793;
public const int ERROR_PASSWORD_EXPIRED = 1330;
public static int CheckUserLogon(string username, string password, string domain_fqdn)
{
int errorCode = 0;
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain_fqdn, "ADMIN_USER", "PASSWORD"))
{
if (!pc.ValidateCredentials(username, password))
{
IntPtr token = new IntPtr();
try
{
if (!LogonUser(username, domain_fqdn, password, LogonTypes.Network, LogonProviders.Default, out token))
{
errorCode = Marshal.GetLastWin32Error();
}
}
catch (Exception)
{
throw;
}
finally
{
CloseHandle(token);
}
}
}
return errorCode;
}
}
https://stackoverflow.com/questions/326818
复制相似问题