我正在尝试运行一个能够远程停止和启动服务的应用程序。通过模拟从加密数据库中读取用户名,密码和域的用户,应用程序需要能够由没有管理员权限的用户使用。
我目前面临的问题是我不确定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();
但是我不确定我插入的代码是否正常,或者我在编写代码时应该添加其他内容。
答案 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的管理员权限。