使用以下方法模擬本地管理員用戶(具有提升的權限)並傳遞必須在模擬上下文中執行的函數。模擬上下文中的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。
但我仍然不明白,爲什麼我的模擬本地管理員不是實例的所有者(即使我在模擬的上下文中創建實例),因此無法訪問數據庫?
解決方案可能很明顯,但我卡住了。
最好的問候,
斯蒂芬