是有一个简单的箱式模拟用户。净?

到目前为止,我已经使用 这类项目的代码 我所有的模拟要求。

是否有一个更好的方式来做到这一点通过使用。净框架?

我有凭证用户组,(用户名、口令、域名),其代表的身份,我需要模仿。

有帮助吗?

解决方案

这里是一些很好的概述。净模拟的概念。

基本上,你会利用这些课程,被开箱的。网的框架:

代码常常可以获得长虽然这就是为什么你看到的许多例子一样,你参考,试图简化该过程。

其他提示

"模拟"中。净空间的一般意味着运行代码在一个特定用户账户。这是一个有所独立的概念比让访问,用户账户通过一个用户名和密码,虽然这两种想法对在一起频繁。我将描述他们两个,然后再说明如何使用我的 SimpleImpersonation 库,其使用他们内部。

模拟

在APIs对于模拟提供。净过 System.Security.Principal 名字空间:

  • 新代码(.净4.6+,.净的核心,等等)。 一般应用 WindowsIdentity.RunImpersonated, 接受一个手柄牌的用户账户,然后一个 ActionFunc<T> 用于代码来执行。

    WindowsIdentity.RunImpersonated(tokenHandle, () =>
    {
        // do whatever you want as this user.
    });
    

    var result = WindowsIdentity.RunImpersonated(tokenHandle, () =>
    {
        // do whatever you want as this user.
        return result;
    });
    
  • 老年码用 WindowsIdentity.Impersonate 方法检索 WindowsImpersonationContext 对象。实现这个目的 IDisposable, ,所以一般应从 using 块。

    using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(tokenHandle))
    {
        // do whatever you want as this user.
    }
    

    虽然这API仍然存在。净框架,它一般应当是可以避免的,并不可用。净的核心。净的标准。

访问的用户帐户

API使用用户名和密码,以获得一个用户账户,在窗 LogonUser -这是一个Win32地API。没有目前有一个内置。净API调用,所以必须采P/调用。

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

这是基本定义,但是还有很多要考虑到实际使用它的生产:

  • 获得处理的"安全"访问的模式。
  • 闭的地适当处理
  • 代码的访问权的安全(CAS)的信任水平(。净框架仅)
  • 传递 SecureString 当你可以收集一个安全地通过用户的键盘输入。

量的代码来编写,以说明所有这一切都是超出了什么应该是在一个计算器的答案,恕我直言。

合并和更容易的方法

而不是编写所有这自己,考虑采用我的 SimpleImpersonation 库,它结合了模拟和用户接成一个单一的API。它的工作原理以及在现代和老年码基地,同样的简单的API:

var credentials = new UserCredentials(domain, username, password);
Impersonation.RunAsUser(credentials, logonType, () =>
{
    // do whatever you want as this user.
}); 

var credentials = new UserCredentials(domain, username, password);
var result = Impersonation.RunAsUser(credentials, logonType, () =>
{
    // do whatever you want as this user.
    return something;
});

注意,它非常类似 WindowsIdentity.RunImpersonated API,但不需要你知道什么令牌处理。

这是API的版本为3.0.0.看到该项目自述的更多详细信息。还注意到,以前版本的图书馆使用的一个API的 IDisposable 模式,类似于 WindowsIdentity.Impersonate.较新版本的安全得多,两者都仍然在内部使用。

这可能是你想要的:

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

但我真的需要更多细节来帮助你。您可以使用配置文件进行模拟(如果您尝试在网站上执行此操作),或者通过方法装饰器(属性)进行模拟,如果它是WCF服务,或者通过......您可以理解。

另外,如果我们谈论模仿调用特定服务(或Web应用程序)的客户端,则需要正确配置客户端,以便它传递适当的令牌。

最后,如果您真正想做的是委托,您还需要正确设置AD,以便信任用户和计算机进行委派。

修改结果 看一下 这里 ,看看如何冒充不同的用户,以及进一步的文档。

这是我的马特约翰逊的vb.net端口的答案。我为登录类型添加了一个枚举。 LOGON32_LOGON_INTERACTIVE是第一个适用于sql server的枚举值。我的连接字符串只是受信任的。连接字符串中没有用户名/密码。

  <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语句来包含一些代码才能运行模拟。

从我之前的回答中查看更多细节 我创建了一个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
}

我知道我参加派对的时间已经很晚了,但我认为该图书来自 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#)使用网络凭据进行模拟

如果您需要模拟登录以获得网络凭据,则可以使用我的示例,但它有更多选项。

您可以使用此解决方案。 (使用nuget包) 源代码可在以下网站获得:Github: https://github.com/michelcedric/UserImpersonation

更多细节 https://michelcedric.wordpress。 COM / 2015/09/03 /侵占-didentite敦用户-C-用户模拟/

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top