在 wpf 应用程序中以调试模式检查当前用户凭据

Posted

技术标签:

【中文标题】在 wpf 应用程序中以调试模式检查当前用户凭据【英文标题】:Check current user credentials in debug mode in a wpf application 【发布时间】:2016-06-29 09:56:50 【问题描述】:

我正在尝试运行能够远程停止和启动服务的应用程序。应用程序需要能够被没有管理员权限的用户使用,方法是模拟用户,从加密数据库中读取用户名、密码和域。

我目前面临的问题是我不确定 Impersonate 功能是否正常工作,因此我想在调试模式下检查哪个用户是当前用户。

这是我用来模拟用户的类:

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Security.Permissions;

public class ImpersonateUser

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool LogonUser(
    String lpszUsername,
    String lpszDomain,
    String lpszPassword,
    int dwLogonType,
    int dwLogonProvider,
    ref IntPtr phToken);
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public extern static bool CloseHandle(IntPtr handle);
    private static IntPtr tokenHandle = new IntPtr(0);
    private static WindowsImpersonationContext impersonatedUser;
    // If you incorporate this code into a DLL, be sure to demand that it
    // runs with FullTrust.
    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public void Impersonate(string domainName, string userName, string password)
    
        //try
        
            // Use the unmanaged LogonUser function to get the user token for
            // the specified user, domain, and password.
            const int LOGON32_PROVIDER_DEFAULT = 0;
        // Passing this parameter causes LogonUser to create a primary token.
        const int LOGON32_LOGON_INTERACTIVE = 2;
        tokenHandle = IntPtr.Zero;
        // ---- Step - 1
        // Call LogonUser to obtain a handle to an access token.
        bool returnValue = LogonUser(
        userName,
        domainName,
        password,
        LOGON32_LOGON_INTERACTIVE,
        LOGON32_PROVIDER_DEFAULT,
        ref tokenHandle); // tokenHandle - new security token
        if (false == returnValue)
        
            int ret = Marshal.GetLastWin32Error();
            throw new System.ComponentModel.Win32Exception(ret);
        
        // ---- Step - 2
        WindowsIdentity newId = new WindowsIdentity(tokenHandle);
        // ---- Step - 3
        
            impersonatedUser = newId.Impersonate();
        
    

// Stops impersonation
public void Undo()

    impersonatedUser.Undo();
    // Free the tokens.
    if (tokenHandle != IntPtr.Zero)
    
        CloseHandle(tokenHandle);
                
        

这就是我尝试使用它的方式:

ImpersonateUser iu = new ImpersonateUser();
iu.Impersonate("[domain]","[username]","[password]");

try
    ServiceController service = new ServiceController(serviceName, remoteComputer);
    service.Start();


iu.Undo(); 

但我不确定我插入的代码是否正常,或者我在编写代码时应该添加其他内容。

【问题讨论】:

既然说到调试,你见过#if debug 是的,我看到了,但这不是我需要的。我发现了 Windowsidentity.GetCurrent();我想这就是我想要的。 【参考方案1】:

我找到了我要找的东西,这是对 WindowsIdentity.GetCurrent().Name 的简单调用;返回的是当前使用应用程序的用户,就像我使用 Impersonate() 一样,您需要将布尔值传递给调用,如下所示:WindowsIdentity.GetCurrent(true).Name; Whih 将返回模拟用户。

编辑

此外,我想为其他可能面临相同问题的人添加一些内容,因为我试图在远程计算机上检查用户的权限,这并没有完全解决问题。这就是我使用另一个功能的原因

static bool isAdmin(string username, string machinename)

using (PrincipalContext ctxMacine = new PrincipalContext(ContextType.Machine, machinename))

    using (PrincipalContext ctxDomain = new PrincipalContext(ContextType.Domain))
    
        UserPrincipal up = UserPrincipal.FindByIdentity(ctxDomain, IdentityType.SamAccountName, username);
        GroupPrincipal gp = GroupPrincipal.FindByIdentity(ctxMacine, "Administrators");

        foreach (UserPrincipal usr in gp.GetMembers(true))
        
            if (up != null)
            
                if (up.SamAccountName.ToUpper() == usr.SamAccountName.ToUpper())
                
                    return true;
                
            
        
    

return false;

当这样使用时:

 ImpersonateUser iu = new ImpersonateUser();
        iu.Impersonate(domain, userName, password);

string name = WindowsIdentity.GetCurrent(true).Name;
MessageBox.Show("CurrentUser: " + name + " " + isAdmin(name, remoteComputer));

iu.Undo();

会告诉您您正在模拟的当前用户是否在您尝试访问的远程计算机上具有管理员权限。

【讨论】:

以上是关于在 wpf 应用程序中以调试模式检查当前用户凭据的主要内容,如果未能解决你的问题,请参考以下文章

如何在设计模式下调试 WPF 用户控件?

UWP 应用程序在未处于调试模式时崩溃

如何确保 IsInRole 检查不使用缓存的凭据

强制用户在 iOS 中以编程方式更新应用程序

有没有办法检查 WPF 当前是不是在设计模式下执行?

如何在 Windows 中以编程方式切换用户