下面是我正在使用的一段代码。我可以使用 LogonType 9 和 Provider as 0(默认提供程序)来启动,但其他 Logon 类型(如 LogonType 4 或 5)不起作用。
我的 Windows Server 版本 MS Windows Server 2016 和用户已正确添加到 AdminL_LocalLogonAsBatchJob、AdminL_LocalLogonAsService 和 IIS_USRS 组中。
我可能错过了什么?
public class Impersonate
{
[DllImport("advapi32.dll", SetLastError = true)]
private static extern int LogonUser(IntPtr lpszUsername, IntPtr lpszDomain, IntPtr lpszPassword,
int dwLogonType, int dwLogonProvider, out int phToken);
[DllImport("kernel32.dll")]
private static extern int FormatMessage(int dwFlags, string lpSource, int dwMessageId, int dwLanguageId,
StringBuilder lpBuffer, int nSize, string[] Arguments);
private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x1000;
private static WindowsImpersonationContext winImpersonationContext = null;
public static string ImpersonateUser(string domain, string userName, string password, int logonType, int provider)
{
string msg = string.Empty;
IntPtr UserNamePointer = IntPtr.Zero;
IntPtr PasswordPointer = IntPtr.Zero;
IntPtr DomainNamePointer = IntPtr.Zero;
UserNamePointer = Marshal.SecureStringToGlobalAllocUnicode(ConvertToSecureString(userName));
PasswordPointer = Marshal.SecureStringToGlobalAllocUnicode(ConvertToSecureString(password));
DomainNamePointer = Marshal.SecureStringToGlobalAllocUnicode(ConvertToSecureString(domain));
bool loggedOn = (LogonUser((IntPtr)UserNamePointer, (IntPtr)DomainNamePointer, (IntPtr)PasswordPointer, logonType,
provider, out int userToken) != 0);
if (loggedOn == false)
{
int apiError = Marshal.GetLastWin32Error();
StringBuilder errorMessage = new StringBuilder(1024);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, null, apiError, 0, errorMessage, 1024, null);
msg = errorMessage.ToString();
}
else
{
msg = "Logged On True";
}
if (userToken != 0)
{
WindowsIdentity identity = new WindowsIdentity((IntPtr)userToken);
winImpersonationContext = identity.Impersonate();
}
return msg;
}
private static SecureString ConvertToSecureString(string password)
{
if (password == null)
throw new ArgumentNullException("password");
var securePassword = new SecureString();
foreach (char c in password)
securePassword.AppendChar(c);
securePassword.MakeReadOnly();
return securePassword;
}
public static void UndoImpersonation()
{
if (winImpersonationContext != null)
{
winImpersonationContext.Undo();
}
}
}