System.Security.SecurityException:'不允许请求的注册表访问。'

时间:2018-10-18 06:42:30

标签: c# winforms impersonation

我正在尝试使用本地窗口用户凭据运行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());
        }
    }
}

现在,当我通过本地窗口用户的凭据时,登录成功,并且在加载form时,我会出错,

  

System.Security.SecurityException:'不允许请求的注册表访问。'

这是完整的堆栈跟踪,

  System.ThrowHelper.ThrowSecurityException(ExceptionResource资源)上的

     在Microsoft.Win32.RegistryKey.OpenSubKey(字符串名称,可写布尔值)      在Microsoft.Win32.RegistryKey.OpenSubKey(字符串名称)      在System.Windows.Forms.LinkUtilities.GetIEColor(字符串名称)      在System.Windows.Forms.LinkUtilities.get_IELinkColor()      在System.Windows.Forms.LinkLabel.get_LinkColor()      在System.Windows.Forms.LinkLabel.OnPaint(PaintEventArgs e)      在System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e,Int16层)      在System.Windows.Forms.Control.WmPaint(Message&m)      在System.Windows.Forms.Control.WndProc(Message&m)      在System.Windows.Forms.Label.WndProc(Message&m)      在System.Windows.Forms.LinkLabel.WndProc(Message&msg)      在System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&m)      在System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&m)      在System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)

可能是什么原因?

1 个答案:

答案 0 :(得分:2)

如果您尝试访问另一个用户的注册表配置单元,我想您会发现您需要成为管理员或LocalSystem帐户。

您可以在LoadUserProfileA function Win32 Api

的底部找到一小段信息。
  

从Windows XP Service Pack 2(SP2)和Windows Server 2003开始,   呼叫者必须是管理员或LocalSystem帐户。 是   不足以使呼叫者仅冒充管理员   或LocalSystem帐户。

注意 :(这是推测性的),但是,您可以启动一个新进程(在管理员凭据下)以加载配置文件并访问注册表

相关问题