使用以下方法,我冒充本地管理员用户(具有提升的权限)并传递必须在模拟上下文中执行的函数。
/// <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。
但是我仍然没有得到它,为什么我的模拟本地管理员不是实例的所有者(即使我在模拟的上下文中创建实例),因此无法访问数据库?
解决方案可能很明显,但我被卡住了。
最诚挚的问候,
斯蒂芬
答案 0 :(得分: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;
}