。Net Core下使用模拟时,我似乎无法以其他用户身份启动进程。我在以用户1运行的Linqpad中运行此脚本,并尝试以用户2启动程序。最初,模拟似乎可以正常工作(在RunImpersonated方法中,当前用户的Console.Writelines从User1正确更改为User2)。但是,该进程始终以User1身份运行。
[这是我为了验证RunImpersonated是否有效而进行的许多测试之一(最初的原因是ASP.Net Core App试图模拟当前用户的问题)。这是我能找到的最简单的可复制示例。
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out SafeAccessTokenHandle phToken);
void Main()
{
string domainName = "myDomain";
string userName = "User2";
string passWord = "User2Password";
const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;
// Call LogonUser to obtain a handle to an access token.
SafeAccessTokenHandle safeAccessTokenHandle;
bool returnValue = LogonUser(userName, domainName, passWord,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
out safeAccessTokenHandle);
if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("LogonUser failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}
Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
// Check the identity.
Console.WriteLine("Before impersonation: " + WindowsIdentity.GetCurrent().Name);
// Note: if you want to run as unimpersonated, pass
// 'SafeAccessTokenHandle.InvalidHandle' instead of variable 'safeAccessTokenHandle'
WindowsIdentity.RunImpersonated(
safeAccessTokenHandle,
// User action
() =>
{
// Check the identity.
Console.WriteLine("During impersonation: " + WindowsIdentity.GetCurrent().Name);
Directory.GetFiles(@"C:\TMP\").Dump();
var pi = new ProcessStartInfo
{
WorkingDirectory = @"C:\TMP\",
FileName = @"C:\TMP\TestUser.exe"
};
var proc = Process.Start(pi);
proc.WaitForExit();
}
);
// Check the identity again.
Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name);
}
要模拟运行进程,您可以设置ProcessStartInfo
属性,并使用其他凭据运行应用程序而不会出现任何问题。您不需要使用ProcessStartInfo
。
只需确保其他用户有权访问应用程序的文件夹(在以下示例中为WindowsIdentity.RunImpersonated
)。
App1.exe
这是一个简单的控制台应用程序,仅显示用户名:
C:\App1\
App2.exe
这是另一个运行using System;
using System.Security.Principal;
namespace App1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(WindowsIdentity.GetCurrent().Name);
Console.ReadLine();
}
}
}
并显示用户名的简单控制台应用程序:
App1.exe
前一段时间,我使用了以下代码:
using System;
using System.Diagnostics;
using System.Net;
using System.Security.Principal;
namespace App2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(WindowsIdentity.GetCurrent().Name);
Console.WriteLine("Running App1");
var info = new ProcessStartInfo();
info.FileName = @"C:\App1\App1.exe";
info.Domain = @"DOMAIN";
info.UserName = @"USER";
info.WindowStyle = ProcessWindowStyle.Normal;
info.Password = new NetworkCredential("", "PASSWORD").SecurePassword;
var process = Process.Start(info);
process.WaitForExit();
Console.WriteLine("App1 finished.");
Console.WriteLine(WindowsIdentity.GetCurrent().Name);
Console.ReadLine();
}
}
}
这对我很有用。检查正在运行该进程的用户。有时用户不是管理员或无法模拟。
Processinfo创建新进程。尝试process.start,或者您可以将exe转换为util dll并在utli.testuser代码之类的代码中运行。使用主程序而非exe的dll调用方法。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Text;
using System.Windows;
using Microsoft.Win32.SafeHandles;
namespace ZZZ
{
partial class User : IDisposable
{
private string m_domain;
private string m_user;
private string m_pass;
private WindowsIdentity user;
private SafeTokenHandle safeTokenHandle;
private WindowsImpersonationContext impContext;
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
out SafeTokenHandle phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private extern static bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool RevertToSelf();
//For the current user
public User()
{
user = WindowsIdentity.GetCurrent();
}
// For custom user
public User(string domain, string user, string password, bool doImepsonate = false)
{
m_domain = domain;
m_user = user;
m_pass = password;
if (doImepsonate) this.Impersonate();
}
// If it's intended to incorporate this code into a DLL, then demand FullTrust.
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public void Impersonate()
{
if (impContext != null) throw new ImpersonationException();
try
{
// Get the user token for the specified user, domain, and password using the unmanaged LogonUser method.
// The local machine name can be used for the domain name to impersonate a user on this machine.
const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;
// Call LogonUser to obtain a handle to an access token.
bool returnValue = LogonUser(
m_user,
m_domain,
m_pass,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
out safeTokenHandle);
if (returnValue == false)
{
int ret = Marshal.GetLastWin32Error();
throw new Win32Exception(ret);
}
using (safeTokenHandle)
{
// Use the token handle returned by LogonUser.
user = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
impContext = user.Impersonate();
}
}
catch (Exception ex)
{
MessageBox.Show("Exception occurred:\n" + ex.Message);
}
}
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
private void Quit()
{
if (impContext == null) return;
impContext.Undo();
safeTokenHandle.Dispose();
}
#endregion
internal IEnumerable<string> Groups
{
get
{
return user.Groups.Select(p =>
{
IdentityReference ir = null;
try { ir = p.Translate(typeof(NTAccount)); }
catch { }
return ir == null ? null : ir.Value;
});
}
}
}
// Win32 API part
internal sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle() : base(true) { }
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
internal sealed class ImpersonationException : Exception
{
public ImpersonationException() : base("The user is already impersonated.") { }
}
}