我使用了常见的模拟代码并且它运行得很好,直到我在域中插入随机'dggdgsdg' - 然而它仍然有效...
if (LogonUser(Username, Domain, Password, Logon32LogonInteractive, Logon32ProviderDefault, ref existingTokenHandle) &&
DuplicateToken(existingTokenHandle, (int)SecurityImpersonationLevel.SecurityDelegation, ref duplicateTokenHandle))
{
Identity = new WindowsIdentity(duplicateTokenHandle);
ImpersonationContext = Identity.Impersonate();
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
我在我的域名上使用了一些TestUser,但它确实有效。我然后切换域,随意废话'werwerhrg',它冒充我的域名上的TestUser!为什么?我希望抛出异常,为什么它在起作用呢?
private const int Logon32LogonInteractive = 2;
private const int Logon32ProviderDefault = 0;
public enum SecurityImpersonationLevel
{
SecurityAnonymous = 0,
SecurityIdentification = 1,
SecurityImpersonation = 2,
SecurityDelegation = 3
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private extern static bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool DuplicateToken(IntPtr existingTokenHandle, int securityImpersonationLevel, ref IntPtr duplicateTokenHandle);
答案 0 :(得分:4)
我认为答案在于如何执行身份验证。 LogonUser
将尝试将您登录到其执行的本地计算机上。如果此计算机位于域中,则将根据AD控制器检查您的密码并进行验证。
但是,如果您提供域名,则无法找到它将作为后备版本对其自己的本地用户群进行身份验证。在本地它将使用NTLM(当客户端和服务器是同一台机器时使用NTLM)。 NTLM验证密码哈希值和用户名,似乎不打扰域名(ref doc)。
如果您使用UPN format instead and set domain to null,那么如果域名不存在,您将收到错误,并获得您想要的结果。
这类似于我在两台计算机上创建一个密码为B的用户A,然后这些用户可以使用本地权限访问彼此的计算机,而无需登录。
所有这一切都是为什么你应该远离域名世界中的本地帐户(至少使用相同的用户名,作为前缀),以及为什么非域名计算机不能在网络。如果可以而不是NTLM,为什么要全部使用Kerberos。