用指定账号运行代码
需要调用Windows登陆函数,从AdvAPI32.dll里面导入3个函数LogonUser,DuplicateToken和CloseHandle。具体过程和代码一并写在下面:
从Dll导入3个Windows函数
- [DllImport("advapi32.dll", SetLastError = true)]
- private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
- [DllImport("advapi32.dll", SetLastError = true)]
- private static extern bool DuplicateToken(IntPtr ExistingTokenHandle, Int32 ImpersonationLevel, out IntPtr DuplicateTokenHandle);
- [DllImport("advapi32.dll", SetLastError = true)]
- private static extern bool CloseHandle(IntPtr hHandle);
定义一些枚举变量
定义Windows函数所需的枚举变量
- public enum WindowsLogonType
- {
- INTERACTIVE = 2,
- NETWORK = 3,
- BATCH = 4,
- SERVICE = 5,
- UNLOCK = 7,
- NETWORK_CLEARTEXT = 8,
- NEW_CREDENTIALS = 9
- }
- public enum ImpersonationLevel
- {
- SecurityAnonymous,
- SecurityIdentification,
- SecurityImpersonation,
- SecurityDelegation
- }
- const Int32 LOGON32_PROVIDER_DEFAULT = 0;
开始登陆过程:
登陆过程代码
- IntPtr hToken = IntPtr.Zero;
- WindowsIdentity windowsIdentity;
- if (LogonUser(username, domain, password, LOGON32_LOGON_SERVICE, LOGON32_PROVIDER_DEFAULT, out hToken))
- {
- windowsIdentity = new WindowsIdentity(hToken);
- WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate();
- //Code here running with new credential
- impersonationContext.Undo();
- //exit new credential context, old credential become active.
- }
- else
- {
- int ret = Marshal.GetLastWin32Error();
- Console.WriteLine("Logon as service failed, Error Code: " + ret.ToString());
- }
- if (hToken != IntPtr.Zero) CloseHandle(hToken);
Windows登陆后返回一个句柄,拿着这个句柄可以生成一个WindowsIdentity,然后WindowsIdentity的Impersonate函数会把当前账号入栈,新帐号激活,并且返回一个WindowsImpersonationContext。这时后面的代码就运行在新帐号权限下面,想返回之前的账号时用WindowsImpersonationContext的Undo函数就可以撤销账号的更改,旧帐号激活。