C# 如何验证域凭据?
我想根据域控制器验证一组凭据。e、 g:C# 如何验证域凭据?,c#,windows,security,authentication,C#,Windows,Security,Authentication,我想根据域控制器验证一组凭据。e、 g: Username: STACKOVERFLOW\joel Password: splotchy 方法1。使用模拟查询Active Directory 很多人建议在Active Directory中查询一些东西。如果引发异常,则您知道凭据无效-如中所建议的 然而,有一些严重的问题: 您不仅对域帐户进行身份验证,而且还进行隐式授权检查。也就是说,您正在使用模拟令牌从广告中读取属性。如果有效的帐户没有读取广告的权限怎么办?默认情况下,所有用户都具有读取权限,
Username: STACKOVERFLOW\joel
Password: splotchy
方法1。使用模拟查询Active Directory
很多人建议在Active Directory中查询一些东西。如果引发异常,则您知道凭据无效-如中所建议的
然而,有一些严重的问题:
LogonUser()
将失败
验证一组域凭据的正确方法是什么
我碰巧是从托管代码中调用的,但这是一个一般的Windows问题。可以假设客户已经安装了.NET Framework 2.0。C#在.NET 3.5中使用 这将针对当前域进行验证。查看参数化PrincipalContext构造函数以获取其他选项
using System;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices.AccountManagement;
class WindowsCred
{
private const string SPLIT_1 = "\\";
public static bool ValidateW(string UserName, string Password)
{
bool valid = false;
string Domain = "";
if (UserName.IndexOf("\\") != -1)
{
string[] arrT = UserName.Split(SPLIT_1[0]);
Domain = arrT[0];
UserName = arrT[1];
}
if (Domain.Length == 0)
{
Domain = System.Environment.MachineName;
}
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, Domain))
{
valid = context.ValidateCredentials(UserName, Password);
}
return valid;
}
}
卡西夫·穆斯塔克
加拿大渥太华我正在使用以下代码验证凭据。
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);
}
}
}
下面显示的方法将确认凭据是否正确,如果不正确,则确认密码是否已过期或需要更改
我一直在寻找这样的东西很久了。。。所以我希望这能帮助别人
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;
}
}
以下是如何确定本地用户:
public bool IsLocalUser()
{
return windowsIdentity.AuthenticationType == "NTLM";
}
伊恩·博伊德编辑 你不应该再使用NTLM了。它太旧了,太糟糕了,以至于微软的应用程序验证程序(用于捕获常见的编程错误)如果检测到您使用NTLM,就会发出警告 下面是Application Verifier文档中的一章,介绍了如果有人错误地使用NTLM,他们为什么要进行测试: 为什么需要NTLM插件 NTLM是一种过时的身份验证协议,存在以下缺陷: 可能会危及应用程序和操作系统的安全性 系统。最重要的缺点是缺少服务器 身份验证,允许攻击者诱骗用户 连接到伪造的服务器。作为缺少服务器的必然结果 身份验证时,使用NTLM的应用程序也可能容易受到攻击 被称为“反射”攻击的攻击类型。后者允许 攻击者将用户的身份验证对话劫持到 合法服务器,并使用它向 用户的计算机。NTLM的漏洞及其利用方法 是增加安全领域研究活动的目标 社区 尽管Kerberos已经存在很多年了,但是许多应用程序 仍然编写为仅使用NTLM。这不必要地降低了成本 应用程序的安全性。但是,Kerberos不能完全取代NTLM 场景–主要是客户机需要对其进行身份验证的场景 未加入域(可能是家庭网络)的系统 其中最常见的一种)。协商安全包允许 尽可能使用Kerberos的向后兼容折衷方案 只有在没有其他选项时才恢复为NTLM。交换码 使用协商而不是NTLM将显著增加 为我们的客户提供安全保护,同时引入很少或没有应用程序 相容性。谈判本身并不是一颗灵丹妙药——确实如此 攻击者可以强制降级到NTLM,但这些都是 显然更难利用。然而,一个直接的问题是: 改进之处在于编写的应用程序能够正确使用协商 自动对NTLM反射攻击免疫 最后,我要提醒大家不要在将来使用NTLM 在Windows版本中,可以禁用
public bool IsLocalUser()
{
return windowsIdentity.AuthenticationType == "NTLM";
}
APIs(parameter) Used by Application Incorrect Value Correct Value
===================================== =============== ========================
AcquireCredentialsHandle (pszPackage) “NTLM” NEGOSSP_NAME “Negotiate”