.net 常识 impersonate user 模拟用户
在.net中 程序运行的时候的权限一般等于运行这个程序的帐号的权限
例如asp.net一般是 network service
console一般是当前用户
计划任务中也可以指定用什么帐号运行当前的程序
asp.net中也可以在web.config中指定用什么帐号运行当前程序
本文介绍了如果在你知道用户名,或者是用户名和密码的情况下 使用特定的帐号密码执行特定的代码,这样你在运行时就可以切换当前程序的帐号和权限以完成特定的目标
1.远程操作不同的机器需要不同的权限 (如果没有AD的话)
2.将程序切换到其他AD去
3.利用已知的帐号和密码,在运行时提高权限
实现方式1,只知道帐号不知道密码,(这种执行方式是受限的,不完全的模拟)
以下代码修改了线程本身的principal,就是执行线程的代理用户
private static void SetThreadPrincipal(string loginId)
{
string[] roles = Roles.GetRolesForUser(loginId);
System.Security.Principal.IIdentity userIdentity = new System.Security.Principal.GenericIdentity(loginId);
System.Security.Principal.IPrincipal userPrincipal = new System.Security.Principal.GenericPrincipal(userIdentity, roles);
Thread.CurrentPrincipal = userPrincipal;
}
实现方式2 知道帐号密码和域(直接用新的帐号密码登录执行新的操作)
参考以下代码....有点长
public static bool ImpersonateValidUser(String userName, String domain, String password)
{
//ServiceContext.SetThreadPrincipal();
WindowsImpersonationContext impersonationContext;
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if (RevertToSelf())
{
if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
#region win32 api extend method
[DllImport("advapi32.dll")]
static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern bool CloseHandle(IntPtr handle);
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_PROVIDER_DEFAULT = 0;
#endregion
BTW 1:如果想修改整个程序的Principal 一般我们只要调用AppDomain.CurrentDomain.SetPrincipal 就可以了 (大部分.net程序都只有一个域)
BTW 2:另外由于修改了当前的principal,也就是说你换了一个帐号执行当前代码,一般情况下执行完操作以后要记得换回原来的帐号...(不同帐号对应不同操作的情况)
WindowsIdentity WindowsIdentity_1024 = WindowsIdentity.GetCurrent();
try
{
//......operation
}
finally
{
if(WindowsIdentity_1024!=null)
WindowsIdentity_1024.Impersonate();
}