2013-11-20 154 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; 
    }