系统安全性异常:'请求的注册表访问被拒绝。'

3

我正在尝试使用本地窗口用户凭据运行我的winform应用程序,为此我正在使用以下类进行模拟:

impersonation
public class Impersonation
{

    /// <summary>
    /// Impersonate given logon information.
    /// </summary>
    /// <param name="logon">Windows logon name.</param>
    /// <param name="password">password</param>
    /// <param name="domain">domain name</param>
    /// <returns></returns>
    public static bool Impersonate(string logon, string password, string domain)
    {
        WindowsIdentity tempWindowsIdentity;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;

        if (LogonUser(logon, domain, password, LOGON32_LOGON_INTERACTIVE,
        LOGON32_PROVIDER_DEFAULT, ref token) != 0)
        {

            if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
            {
                tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                impersonationContext = tempWindowsIdentity.Impersonate();
                if (null != impersonationContext) return true;
            }
        }

        return false;
    }

    /// <summary>
    /// Unimpersonate.
    /// </summary>
    public static void UnImpersonate()
    {
        impersonationContext.Undo();
    }

    [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
    public static extern int LogonUser(
    string lpszUserName,
    String lpszDomain,
    String lpszPassword,
    int dwLogonType,
    int dwLogonProvider,
    ref IntPtr phToken);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public extern static int DuplicateToken(
    IntPtr hToken,
    int impersonationLevel,
    ref IntPtr hNewToken);

    private const int LOGON32_LOGON_INTERACTIVE = 2;
    private const int LOGON32_LOGON_NETWORK_CLEARTEXT = 4;
    private const int LOGON32_PROVIDER_DEFAULT = 0;
    private static WindowsImpersonationContext impersonationContext;
}

现在这里是“winform”启动代码的代码:

static class Program
{
    [STAThread]
    static void Main()
    {
        try
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            string userName = Microsoft.VisualBasic.Interaction.InputBox("Enter User Name", "User Name");
            string password = Microsoft.VisualBasic.Interaction.InputBox("Enter Password", "Password");

            if (!Impersonation.Impersonate(userName, password, Environment.MachineName))
            {
                MessageBox.Show("Login failed.");
                return;
            }

            Application.Run(new Form1());

            Impersonation.UnImpersonate();
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error: " + ex.ToString());
        }
    }
}

现在,当我使用本地Windows用户的凭据进行登录时,登录成功,但在加载表单时出现错误, System.Security.SecurityException: 'Requested registry access is not allowed.' 以下是完整的堆栈跟踪,

at System.ThrowHelper.ThrowSecurityException(ExceptionResource resource) at Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean writable) at Microsoft.Win32.RegistryKey.OpenSubKey(String name) at System.Windows.Forms.LinkUtilities.GetIEColor(String name) at System.Windows.Forms.LinkUtilities.get_IELinkColor() at System.Windows.Forms.LinkLabel.get_LinkColor() at System.Windows.Forms.LinkLabel.OnPaint(PaintEventArgs e) at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer) at System.Windows.Forms.Control.WmPaint(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.Label.WndProc(Message& m) at System.Windows.Forms.LinkLabel.WndProc(Message& msg) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

可能的原因是什么?
1个回答

2
如果您尝试访问另一个用户的注册表,我认为您会发现需要管理员或LocalSystem帐户。您可以在LoadUserProfileA函数 Win32 Api底部找到一小段信息。
引用:“从Windows XP Service Pack 2(SP2)和Windows Server 2003开始,调用者必须是管理员或LocalSystem帐户。仅模拟管理员或LocalSystem帐户对调用者来说是不够的。”
注意:(这是推测)但是,您可能会启动一个新进程(在管理员凭据下)来加载配置文件并访问注册表。

一个解决方法是获取密钥的所有权,为您模拟的用户更改权限,然后将所有权重新设置为原始所有者的SID。然而,不建议这样做,因为用户现在会拥有他不应该拥有的权限。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接