Aar*_*ide 3 c# impersonation mstest winforms
我的Winforms应用程序根据当前进程中找到的组成员身份设置权限.
我刚刚在MSTEST进行了单元测试.
我想以其他用户身份运行它,以便我可以验证预期的行为.
这就是我的拍摄方式:
[TestMethod]
public void SecuritySummaryTest1()
{
Impersonate(@"SomeDomain\AdminUser", password);
var target = new DirectAgentsSecurityManager();
string actual = target.SecuritySummary;
Assert.AreEqual(
@"Default=[no]AccountManagement=[no]MediaBuying=[no]AdSales=[no]Accounting=[no]Admin=[YES]", actual);
}
[TestMethod]
public void SecuritySummaryTest2()
{
Impersonate(@"SomeDomain\AccountantUser", password);
var target = new DirectAgentsSecurityManager();
string actual = target.SecuritySummary;
Assert.AreEqual(
@"Default=[no]AccountManagement=[YES]MediaBuying=[no]AdSales=[no]Accounting=[YES]Admin=[NO]", actual);
}
Run Code Online (Sandbox Code Playgroud)
public class UserCredentials
{
private readonly string _domain;
private readonly string _password;
private readonly string _username;
public UserCredentials(string domain, string username, string password)
{
_domain = domain;
_username = username;
_password = password;
}
public string Domain { get { return _domain; } }
public string Username { get { return _username; } }
public string Password { get { return _password; } }
}
public class UserImpersonation : IDisposable
{
private readonly IntPtr _dupeTokenHandle = new IntPtr(0);
private readonly IntPtr _tokenHandle = new IntPtr(0);
private WindowsImpersonationContext _impersonatedUser;
public UserImpersonation(UserCredentials credentials)
{
const int logon32ProviderDefault = 0;
const int logon32LogonInteractive = 2;
const int securityImpersonation = 2;
_tokenHandle = IntPtr.Zero;
_dupeTokenHandle = IntPtr.Zero;
if (!Advapi32.LogonUser(credentials.Username, credentials.Domain, credentials.Password,
logon32LogonInteractive, logon32ProviderDefault, out _tokenHandle))
{
var win32ErrorNumber = Marshal.GetLastWin32Error();
// REVIEW: maybe ImpersonationException should inherit from win32exception
throw new ImpersonationException(win32ErrorNumber, new Win32Exception(win32ErrorNumber).Message,
credentials.Username, credentials.Domain);
}
if (!Advapi32.DuplicateToken(_tokenHandle, securityImpersonation, out _dupeTokenHandle))
{
var win32ErrorNumber = Marshal.GetLastWin32Error();
Kernel32.CloseHandle(_tokenHandle);
throw new ImpersonationException(win32ErrorNumber, "Unable to duplicate token!", credentials.Username,
credentials.Domain);
}
var newId = new WindowsIdentity(_dupeTokenHandle);
_impersonatedUser = newId.Impersonate();
}
public void Dispose()
{
if (_impersonatedUser != null)
{
_impersonatedUser.Undo();
_impersonatedUser = null;
if (_tokenHandle != IntPtr.Zero)
Kernel32.CloseHandle(_tokenHandle);
if (_dupeTokenHandle != IntPtr.Zero)
Kernel32.CloseHandle(_dupeTokenHandle);
}
}
}
internal static class Advapi32
{
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL,
out IntPtr DuplicateTokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword,
int dwLogonType, int dwLogonProvider, out IntPtr phToken);
}
internal static class Kernel32
{
[DllImport("kernel32.dll", SetLastError = true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
}
Run Code Online (Sandbox Code Playgroud)
我没有包含ImpersonationException的实现,但它并不重要.它没有做任何特别的事情.
如果这足以满足您的用例,您还可以直接设置当前主体:
System.Threading.Thread.CurrentPrincipal
= new WindowsPrincipal(new WindowsIdentity("testuser@contoso.com"));
Run Code Online (Sandbox Code Playgroud)
根据此连接页面,在每种测试方法之后恢复主体。请注意,如果与检查主体的 Web 服务客户端一起使用,则此方法将不起作用(对于此用例,Jim Bolla 的解决方案工作得很好)。