2013-11-20 179 views
0

使用以下方法模擬本地管理員用戶(具有提升的權限)並傳遞必須在模擬上下文中執行的函數。模擬上下文中的LocalDB操作

/// <summary> 
    /// Attemps to impersonate a given windows user and to run a given function within the impersonation context. 
    /// </summary> 
    /// <param name="userInformation">The user name and password for impersonation.</param> 
    /// <param name="functionAsImpersonatedUser">The function to be executed within the impersonation context.</param> 
    /// <returns>True if the operation was successful, false and an error message otherwise.</returns> 
    public static BooleanResult ExecuteAsImpersonatedUser(UserInformation userInformation, Func<BooleanResult> functionAsImpersonatedUser) 
    { 
     BooleanResult retval = new BooleanResult(); 
     IntPtr returnedToken = IntPtr.Zero; 
     try 
     { 
      //Note: the logon type 'batch' seems to return a token with elevated privileges 
      bool success = NativeMethods.LogonUser(userInformation.Name, userInformation.Domain ?? ".", userInformation.Password, (int)LogonType.Batch, (int)LogonProvider.Default, out returnedToken); 
      if (false == success) 
      { 
       int ret = Marshal.GetLastWin32Error(); 
       throw new Win32Exception(ret); 
      } 
      using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(returnedToken)) 
      { 
       retval = functionAsImpersonatedUser(); 
      } 
     } 
     catch (OutOfMemoryException o) 
     { 
      string logMessage = String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorImpersonatingUser, userInformation.Domain, userInformation.Name, o.Message); 
      retval.ProcessGeneralException(o, logMessage); 
     } 
     catch (SecurityException s) 
     { 
      string logMessage = String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorImpersonatingUser, userInformation.Domain, userInformation.Name, s.Message); 
      retval.ProcessGeneralException(s, logMessage); 
     } 
     catch (UnauthorizedAccessException u) 
     { 
      string logMessage = String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorImpersonatingUser, userInformation.Domain, userInformation.Name, u.Message); 
      retval.ProcessGeneralException(u, logMessage); 
     } 
     catch (Win32Exception w) 
     { 
      string logMessage = String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorImpersonatingUser, userInformation.Domain, userInformation.Name, w.Message); 
      retval.ProcessGeneralException(w, logMessage); 
     } 
     finally 
     { 
      if (NativeMethods.CloseHandle(returnedToken)) 
       LogUtility.Instance.Write(String.Format(CultureInfo.InvariantCulture, TranslationStrings.CloseUserHandleSuccess, userInformation.Domain, userInformation.Name), 4); 
      else 
       LogUtility.Instance.Write(String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorCloseUserHandle, userInformation.Domain, userInformation.Name), 2); 
     } 
     return retval; 
    } 

沒有問題,到目前爲止。通過LogonType.Batch替換LogonType.Interactive後,似乎甚至會以特權提升用戶令牌。

模擬上下文中的函數根據需要創建localDB實例,啓動它並嘗試使用安全腳本和SMO設置數據庫。我遇到的第一件事情是,實例所有者不是模擬的本地管理員,爲什麼會這樣:我對模擬或localDB的工作原理有錯誤的理解?因爲只有使用像「Data Source =(localdb)。[instanceName]; Initial Catalog = [databaseName]; Integrated Security = true」這樣的連接纔可以使用。這因此導致ConnectionFailureException。

但我仍然不明白,爲什麼我的模擬本地管理員不是實例的所有者(即使我在模擬的上下文中創建實例),因此無法訪問數據庫?

解決方案可能很明顯,但我卡住了。

最好的問候,

斯蒂芬

回答

1

我傻!

通過設置在這個過程中動詞,用戶名和密碼屬性啓動信息就可以安裝LocalDB實例,並指定一個不同的所有者...

public static ConsoleOutputResult CreateInstance(UserInformation user) 
    { 
     if (user == null) 
      throw new ArgumentNullException("user"); 

     ConsoleOutputResult retval = new ConsoleOutputResult(); 
     try 
     { 
      ProcessStartInfo startInfo = new ProcessStartInfo(Path.Combine(localDBPath, "SqlLocalDB.exe"), String.Format(CultureInfo.InvariantCulture, "create {0}", instanceName)) 
      { 
       CreateNoWindow = true, 
       Domain = user.Domain, 
       ErrorDialog = false, 
       LoadUserProfile = true, 
       Password = user.Password.ConvertToSecureString(), 
       RedirectStandardError = true, 
       RedirectStandardOutput = true, 
       UserName = user.Name, 
       UseShellExecute = false, 
       Verb = "runas" 
      }; 
      using (Process process = Process.Start(startInfo)) 
      { 
       process.WaitForExit(); 
       retval.Error = process.StandardError.ReadToEnd(); 
       retval.Output = process.StandardOutput.ReadToEnd(); 
       retval.Success = String.IsNullOrEmpty(retval.Error); 
       if (retval.Success) 
        LogUtility.Instance.Write(retval.Output, 4); 
      } 
     } 
     catch (Exception e) 
     { 
      string logMessage = String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorCreateLocalDB, e.Message); 
      retval.ProcessGeneralException(e, logMessage); 
      throw new SmartAppWizardException(logMessage, e.InnerException); 
     } 
     return retval; 
    }