2015-07-20 82 views
0

從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也是如此,這就像是在一個黑匣子裏工作。

回答

0

我們必須使用本機窗口方法: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); 
       } 
      } 
     } 
    } 
相關問題