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

时间:2016-06-29 09:56:51

标签: c# wpf impersonation

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

我目前面临的问题是我不确定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(); 

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

1 个答案:

答案 0 :(得分:0)

我找到了我要找的东西,这是对WindowsIdentity.GetCurrent()的简单调用。如果返回的是当前正在使用该应用程序的用户,并且在我的情况下你正在使用Impersonate(),则需要将boolean传递给调用,如下所示: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();

将告诉您当前正在模拟的用户是否具有您尝试访问的remoteComputer的管理员权限。