模拟上下文中的LocalDB操作

时间:2013-11-20 13:08:40

标签: impersonation 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 个答案:

答案 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;
    }