Impersonate让你的子线程也具有主线程的执行权限

系统部署在某些复杂的网络环境中,对权限的控制较为严格,无法给IIS用户授予更多的权限,而有些操作(比如对数据库的操作)又必须拥有权限才能成功。

 

ASP.NET在后台使用多线程进行数据处理时,主线程可以获取IIS用户的权限,而子线程则不能获取到权限,进而导致子线程的执行过程失败。

为了让子线程也和主线程拥有相同的权限,则可以使用Impersonate方法。

 

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;


/// <summary>
/// Summary description for ThreadImpersonate
/// </summary>
public class ThreadImpersonate
{
    
public const int LOGON32_LOGON_INTERACTIVE = 2;
    
public const int LOGON32_PROVIDER_DEFAULT = 0;

    WindowsImpersonationContext impersonationContext;

    [DllImport(
"advapi32.dll")]
    
public 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)]
    
public static extern int DuplicateToken(IntPtr hToken,
        
int impersonationLevel,
        
ref IntPtr hNewToken);

    [DllImport(
"advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    
public static extern bool RevertToSelf();

    [DllImport(
"kernel32.dll", CharSet = CharSet.Auto)]
    
public static extern bool CloseHandle(IntPtr handle);

    
public bool ImpersonateValidUser(String userName, String domain, String password)
    {
        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, 2ref 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;
    }

    
public void UndoImpersonation()
    {
        impersonationContext.Undo();

    } 

ThreadImpersonate类中的ImpersonateValidUser方法进行代码执行权限的设置,前提是在ASP.NET应用程序部署的服务器中建立一个具有某些权限的用户,userName即为用户名,domain为域名,如果服务器不在域中则为空,password为用户的密码。

下面示例中演示了如何使用Impersonate

        protected void Page_Load(object sender, EventArgs e)
        {
            Thread.CurrentThread.Name 
= "Main Thread";
            ThreadIdentity();

            
for (int i = 0; i < 5; i++)
            {

                Thread t 
= new Thread(new ThreadStart(ThreadIdentity));
                t.Name 
= string.Format("Thread{0}", i + 1);
                t.Start();
            }
        }

        
protected void ThreadIdentity()
        {
            ThreadImpersonate impersonateMgr 
= new ThreadImpersonate();

            
string threadName = Thread.CurrentThread.Name;
            
string identityName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
            
if (impersonateMgr.ImpersonateValidUser("test1"string.Empty, "test"))
            {
                 threadName 
= Thread.CurrentThread.Name;
                 identityName 
= System.Security.Principal.WindowsIdentity.GetCurrent().Name;
                
// Do Something in your code...
                impersonateMgr.UndoImpersonation();
            }

       } 


调用Impersonate时应在子线程内部调用,否则子线程无法获取到权限

 

 

 

posted @ 2011-08-15 00:17  Async Liu  阅读(599)  评论(0编辑  收藏  举报