ASP.NET Web处理程序运行命令作为请求用户

问题描述:

从Web处理程序(xxx.ashx)我需要运行一个命令作为使用该网页并发送请求的同一用户。我有使用模拟的IIS设置,在我的.ashx代码中显示它正在模拟用户,然后使用C#Process.start()来运行该命令。 (这是我正在运行的.cmd文件)ASP.NET Web处理程序运行命令作为请求用户

问题是.cmd文件以分配给应用程序池而不是Web用户的用户身份运行。我甚至试过这段代码:

WindowsImpersonationContext impersonationContext =((WindowsIdentity)System.Security.Principal.WindowsIdentity.GetCurrent())。Impersonate();

这可能是一个问题:我写了.ashx文件,并把它放在IIS wwwroot/myapp文件夹下,并从网页浏览器的URL调用它。我已经使用DefaultAppPool用户和OS用户设置了应用程序池,但没有区别。

我是一个IIS的新手& ASP也是如此,这就像是在一个黑匣子里工作。

我们必须使用本机窗口方法:CreateProcessAsUser(),并且必须调用DuplicateTokenEx()来复制安全性令牌。

<%@ WebHandler Language="C#" Class="batchRunSAS" %> 
    using System; 

    using System; 
    using System.IO; 
    using System.Web; 
    using System.Diagnostics; 
    using System.Security.Principal; 

    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Security; 
    using System.Runtime.InteropServices; 
    using System.ComponentModel; 

      public class batchRun : IHttpHandler 
    { 
     public void ProcessRequest (HttpContext context) 
     { 
      //Call DuplicateTokenEx 
      //https://msdn.microsoft.com/en-us/library/ms682429(VS.85).aspx 
      //http://stackoverflow.com/questions/9095909/createprocessasuser-creating-window-in-active-session 
      Process process = null; 

      process = NativeMethods.CreateProcessAsUser("C:\\temp\\test.exe"); 
     } 

     public bool IsReusable 
     { 
      get { return false; } 
     } 

     [SuppressUnmanagedCodeSecurity] 
     class NativeMethods 
     { 
      [StructLayout(LayoutKind.Sequential)] 
      public struct STARTUPINFO 
      { 
       public Int32 cb; 
       public string lpReserved; 
       public string lpDesktop; 
       public string lpTitle; 
       public Int32 dwX; 
       public Int32 dwY; 
       public Int32 dwXSize; 
       public Int32 dwXCountChars; 
       public Int32 dwYCountChars; 
       public Int32 dwFillAttribute; 
       public Int32 dwFlags; 
       public Int16 wShowWindow; 
       public Int16 cbReserved2; 
       public IntPtr lpReserved2; 
       public IntPtr hStdInput; 
       public IntPtr hStdOutput; 
       public IntPtr hStdError; 
      } 

      [StructLayout(LayoutKind.Sequential)] 
      public struct PROCESS_INFORMATION 
      { 
       public IntPtr hProcess; 
       public IntPtr hThread; 
       public Int32 dwProcessID; 
       public Int32 dwThreadID; 
      } 

      [StructLayout(LayoutKind.Sequential)] 
      public struct SECURITY_ATTRIBUTES 
      { 
       public Int32 Length; 
       public IntPtr lpSecurityDescriptor; 
       public bool bInheritHandle; 
      } 

      public enum SECURITY_IMPERSONATION_LEVEL 
      { 
       SecurityAnonymous, 
       SecurityIdentification, 
       SecurityImpersonation, 
       SecurityDelegation 
      } 

      public enum TOKEN_TYPE 
      { 
       TokenPrimary = 1, 
       TokenImpersonation 
      } 

      public const int GENERIC_ALL_ACCESS = 0x10000000; 
      public const int CREATE_NO_WINDOW = 0x08000000; 

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

      [ 
       DllImport("advapi32.dll", 
        EntryPoint = "CreateProcessAsUser", SetLastError = true, 
        CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall) 
      ] 
      public static extern bool 
       CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine, 
            ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, 
            bool bInheritHandle, Int32 dwCreationFlags, IntPtr lpEnvrionment, 
            string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, 
            ref PROCESS_INFORMATION lpProcessInformation); 

      [ 
       DllImport("advapi32.dll", 
        EntryPoint = "DuplicateTokenEx") 
      ] 
      public static extern bool 
       DuplicateTokenEx(IntPtr hExistingToken, Int32 dwDesiredAccess, 
           ref SECURITY_ATTRIBUTES lpThreadAttributes, 
           Int32 ImpersonationLevel, Int32 dwTokenType, 
           ref IntPtr phNewToken); 

      public static Process CreateProcessAsUser(string filename, string args) 
      { 
       var hToken = WindowsIdentity.GetCurrent().Token; 
       var hDupedToken = IntPtr.Zero; 

       var pi = new PROCESS_INFORMATION(); 
       var sa = new SECURITY_ATTRIBUTES(); 
       sa.Length = Marshal.SizeOf(sa); 

       try 
       { 
        if (!DuplicateTokenEx(
          hToken, 
          GENERIC_ALL_ACCESS, 
          ref sa, 
          (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, 
          (int)TOKEN_TYPE.TokenPrimary, 
          ref hDupedToken 
         )) 
         throw new Win32Exception(Marshal.GetLastWin32Error()); 

        var si = new STARTUPINFO(); 
        si.cb = Marshal.SizeOf(si); 
        si.lpDesktop = ""; 

        var path = Path.GetFullPath(filename); 
        var dir = Path.GetDirectoryName(path); 

        // Revert to self to create the entire process; not doing this might 
        // require that the currently impersonated user has "Replace a process 
        // level token" rights - we only want our service account to need 
        // that right. 
        using (var ctx = WindowsIdentity.Impersonate(IntPtr.Zero)) 
        { 
         if (!CreateProcessAsUser(
               hDupedToken, 
               path, 
               string.Format("\"{0}\" {1}", filename.Replace("\"", "\"\""), args), 
               ref sa, ref sa, 
               false, 0, IntPtr.Zero, 
               dir, ref si, ref pi 
             )) 
          throw new Win32Exception(Marshal.GetLastWin32Error()); 
        } 

        return Process.GetProcessById(pi.dwProcessID); 
       } 
       finally 
       { 
        if (pi.hProcess != IntPtr.Zero) 
         CloseHandle(pi.hProcess); 
        if (pi.hThread != IntPtr.Zero) 
         CloseHandle(pi.hThread); 
        if (hDupedToken != IntPtr.Zero) 
         CloseHandle(hDupedToken); 
       } 
      } 
     } 
    }