你怎么做在.NET模拟?

有没有一种简单的方式来模仿在.NET中的用户?

到目前为止,我一直在从代码项目中使用这个类来满足我所有的模拟需求。

有没有更好的方式来使用.NET Framework?

我有一个用户凭证集(用户名,密码,域名),代表我需要模仿的身份。

下面是.NET模拟概念的一些很好的概述。

  • Michiel van Otegem:WindowsImpersonationContext变得容易
  • WindowsIdentity.Impersonate方法(检查代码示例)

基本上你将会利用这些在.NET框架中开箱即用的类:

  • WindowsImpersonationContext
  • 的WindowsIdentity

代码通常会变得冗长,这就是为什么你会看到很多例子,比如你所引用的那个,试图简化这个过程。

跳过这个主题的多个post后,我终于想出了一个简单的类来封装所有的模拟逻辑。 它允许你做这样一个简单的调用:

using (new Impersonation(domain, username, password)) { // do whatever you want } 

添加这个类到你的项目中,然后离开你:

 using System; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Security.Principal; using Microsoft.Win32.SafeHandles; namespace MyApplication { [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public class Impersonation : IDisposable { private readonly SafeTokenHandle _handle; private readonly WindowsImpersonationContext _context; const int LOGON32_LOGON_NEW_CREDENTIALS = 9; public Impersonation(string domain, string username, string password) { var ok = LogonUser(username, domain, password, LOGON32_LOGON_NEW_CREDENTIALS, 0, out this._handle); if (!ok) { var errorCode = Marshal.GetLastWin32Error(); throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code {0}.", errorCode)); } this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle()); } public void Dispose() { this._context.Dispose(); this._handle.Dispose(); } [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken); public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid { private SafeTokenHandle() : base(true) { } [DllImport("kernel32.dll")] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool CloseHandle(IntPtr handle); protected override bool ReleaseHandle() { return CloseHandle(handle); } } } } 

请注意,我正在使用logintypes9(新凭据)。 在我的情况下,我需要通过信任的安全连接到一个不同的loginsql服务器,所以这是最好的。 根据您的目的,您可能需要不同的logintypes。 看看这个网站的其他logintypes。


UPDATE

基于持续的积极反馈,我已决定稍微清理一下,并将其存放在图书馆以方便消费。 GitHub上的源代码和文档,可以在NuGet上使用。 请享用!

这可能是你想要的:

 using System.Security.Principal; using(WindowsIdentity.GetCurrent().Impersonate()) { //your code goes here } 

但我真的需要更多的细节来帮助你。 你可以使用configuration文件(如果你想在网站上执行此操作)或通过方法装饰器(属性)(如果它是WCF服务)或通过…你明白了。

另外,如果我们正在讨论模拟一个调用特定服务(或Web应用程序)的客户端,则需要正确configuration客户端,以便传递适当的令牌。

最后,如果你真正想要做的是授权,你也需要正确设置AD,这样用户和机器才能被委托进行授权。

编辑:
看看这里看看如何模仿不同的用户,以及进一步的文档。

这是我的vb.net端口的马特约翰逊的答案。 我添加了logintypes的枚举。 LOGON32_LOGON_INTERACTIVE是第一个为sql server工作的枚举值。 我的连接string只是可信的。 连接string中没有用户名/密码。

  <PermissionSet(SecurityAction.Demand, Name:="FullTrust")> _ Public Class Impersonation Implements IDisposable Public Enum LogonTypes ''' <summary> ''' This logon type is intended for users who will be interactively using the computer, such as a user being logged on ''' by a terminal server, remote shell, or similar process. ''' This logon type has the additional expense of caching logon information for disconnected operations; ''' therefore, it is inappropriate for some client/server applications, ''' such as a mail server. ''' </summary> LOGON32_LOGON_INTERACTIVE = 2 ''' <summary> ''' This logon type is intended for high performance servers to authenticate plaintext passwords. ''' The LogonUser function does not cache credentials for this logon type. ''' </summary> LOGON32_LOGON_NETWORK = 3 ''' <summary> ''' This logon type is intended for batch servers, where processes may be executing on behalf of a user without ''' their direct intervention. This type is also for higher performance servers that process many plaintext ''' authentication attempts at a time, such as mail or Web servers. ''' The LogonUser function does not cache credentials for this logon type. ''' </summary> LOGON32_LOGON_BATCH = 4 ''' <summary> ''' Indicates a service-type logon. The account provided must have the service privilege enabled. ''' </summary> LOGON32_LOGON_SERVICE = 5 ''' <summary> ''' This logon type is for GINA DLLs that log on users who will be interactively using the computer. ''' This logon type can generate a unique audit record that shows when the workstation was unlocked. ''' </summary> LOGON32_LOGON_UNLOCK = 7 ''' <summary> ''' This logon type preserves the name and password in the authentication package, which allows the server to make ''' connections to other network servers while impersonating the client. A server can accept plaintext credentials ''' from a client, call LogonUser, verify that the user can access the system across the network, and still ''' communicate with other servers. ''' NOTE: Windows NT: This value is not supported. ''' </summary> LOGON32_LOGON_NETWORK_CLEARTEXT = 8 ''' <summary> ''' This logon type allows the caller to clone its current token and specify new credentials for outbound connections. ''' The new logon session has the same local identifier but uses different credentials for other network connections. ''' NOTE: This logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon provider. ''' NOTE: Windows NT: This value is not supported. ''' </summary> LOGON32_LOGON_NEW_CREDENTIALS = 9 End Enum <DllImport("advapi32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> _ Private Shared Function LogonUser(lpszUsername As [String], lpszDomain As [String], lpszPassword As [String], dwLogonType As Integer, dwLogonProvider As Integer, ByRef phToken As SafeTokenHandle) As Boolean End Function Public Sub New(Domain As String, UserName As String, Password As String, Optional LogonType As LogonTypes = LogonTypes.LOGON32_LOGON_INTERACTIVE) Dim ok = LogonUser(UserName, Domain, Password, LogonType, 0, _SafeTokenHandle) If Not ok Then Dim errorCode = Marshal.GetLastWin32Error() Throw New ApplicationException(String.Format("Could not impersonate the elevated user. LogonUser returned error code {0}.", errorCode)) End If WindowsImpersonationContext = WindowsIdentity.Impersonate(_SafeTokenHandle.DangerousGetHandle()) End Sub Private ReadOnly _SafeTokenHandle As New SafeTokenHandle Private ReadOnly WindowsImpersonationContext As WindowsImpersonationContext Public Sub Dispose() Implements System.IDisposable.Dispose Me.WindowsImpersonationContext.Dispose() Me._SafeTokenHandle.Dispose() End Sub Public NotInheritable Class SafeTokenHandle Inherits SafeHandleZeroOrMinusOneIsInvalid <DllImport("kernel32.dll")> _ <ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)> _ <SuppressUnmanagedCodeSecurity()> _ Private Shared Function CloseHandle(handle As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function Public Sub New() MyBase.New(True) End Sub Protected Overrides Function ReleaseHandle() As Boolean Return CloseHandle(handle) End Function End Class End Class 

您需要使用Using语句来包含一些代码才能运行模拟。

从我以前的答案查看更多详细信息我已经创build了一个Nuget包Nuget

Github上的代码

示例:您可以使用:

  string login = ""; string domain = ""; string password = ""; using (UserImpersonation user = new UserImpersonation(login, domain, password)) { if (user.ImpersonateValidUser()) { File.WriteAllText("test.txt", "your text"); Console.WriteLine("File writed"); } else { Console.WriteLine("User not connected"); } } 

Vieuw完整的代码:

 using System; using System.Runtime.InteropServices; using System.Security.Principal; /// <summary> /// Object to change the user authticated /// </summary> public class UserImpersonation : IDisposable { /// <summary> /// Logon method (check athetification) from advapi32.dll /// </summary> /// <param name="lpszUserName"></param> /// <param name="lpszDomain"></param> /// <param name="lpszPassword"></param> /// <param name="dwLogonType"></param> /// <param name="dwLogonProvider"></param> /// <param name="phToken"></param> /// <returns></returns> [DllImport("advapi32.dll")] private static extern bool LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); /// <summary> /// Close /// </summary> /// <param name="handle"></param> /// <returns></returns> [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern bool CloseHandle(IntPtr handle); private WindowsImpersonationContext _windowsImpersonationContext; private IntPtr _tokenHandle; private string _userName; private string _domain; private string _passWord; const int LOGON32_PROVIDER_DEFAULT = 0; const int LOGON32_LOGON_INTERACTIVE = 2; /// <summary> /// Initialize a UserImpersonation /// </summary> /// <param name="userName"></param> /// <param name="domain"></param> /// <param name="passWord"></param> public UserImpersonation(string userName, string domain, string passWord) { _userName = userName; _domain = domain; _passWord = passWord; } /// <summary> /// Valiate the user inforamtion /// </summary> /// <returns></returns> public bool ImpersonateValidUser() { bool returnValue = LogonUser(_userName, _domain, _passWord, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref _tokenHandle); if (false == returnValue) { return false; } WindowsIdentity newId = new WindowsIdentity(_tokenHandle); _windowsImpersonationContext = newId.Impersonate(); return true; } #region IDisposable Members /// <summary> /// Dispose the UserImpersonation connection /// </summary> public void Dispose() { if (_windowsImpersonationContext != null) _windowsImpersonationContext.Undo(); if (_tokenHandle != IntPtr.Zero) CloseHandle(_tokenHandle); } #endregion } 

你可以使用这个解决scheme。 (使用nuget包)源代码可在:Github: https : //github.com/michelcedric/UserImpersonation

更多详情https://michelcedric.wordpress.com/2015/09/03/usurpation-didentite-dun-user-c-user-impersonation/

我知道我晚了很晚,但是我认为菲利普·艾伦·哈丁(Phillip Allan-Harding)的图书馆是这个案例和类似案例中最好的一个。

你只需要这样一小段代码:

 private const string LOGIN = "mamy"; private const string DOMAIN = "mongo"; private const string PASSWORD = "HelloMongo2017"; private void DBConnection() { using (Impersonator user = new Impersonator(LOGIN, DOMAIN, PASSWORD, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, LogonProvider.LOGON32_PROVIDER_WINNT50)) { } } 

并添加他的课程:

.NET(C#)模拟与networking凭据

我的例子可以使用,如果你需要模拟login有networking凭据,但它有更多的select。