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