c# - 您如何在 .NET 中进行模拟?

标签 c# .net impersonation

是否有一种开箱即用的简单方法来模拟 .NET 中的用户?

到目前为止,我一直在使用 this class from code project满足我所有的模拟要求。

是否有使用 .NET Framework 的更好方法?

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

最佳答案

.NET 空间中的“模拟”通常意味着在特定用户帐户下运行代码。与通过用户名和密码访问该用户帐户相比,这在某种程度上是一个独立的概念,尽管这两个想法经常结合在一起。

假冒

用于模拟的 API 在 .NET 中通过 System.Security.Principal 提供。命名空间:

  • 较新的代码通常应使用 WindowsIdentity.RunImpersonated ,它接受用户帐户 token 的句柄,然后是 ActionFunc<T>用于执行代码。

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

    var result = WindowsIdentity.RunImpersonated(userHandle, () =>
    {
        // do whatever you want as this user.
        return result;
    });
    

    还有 WindowsIdentity.RunImpersonatedAsync 对于异步任务,在 .NET 5+ 或旧版本上可用,如果你拉入 System.Security.Principal.Windows Nuget 包。

    await WindowsIdentity.RunImpersonatedAsync(userHandle, async () =>
    {
        // do whatever you want as this user.
    });
    

    var result = await WindowsIdentity.RunImpersonated(userHandle, async () =>
    {
        // do whatever you want as this user.
        return result;
    });
    
  • 旧代码使用了 WindowsIdentity.Impersonate 检索 WindowsImpersonationContext 的方法目的。该对象实现了 IDisposable , 所以通常应该从 using 调用 block 。

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

    虽然此 API 仍然存在于 .NET Framework 中,但通常应避免使用。

访问用户帐户

在 Windows 中使用用户名和密码访问用户帐户的 API 是 LogonUser - 这是一个 Win32 native API。目前没有用于调用它的内置托管 .NET API。

[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);

这是基本的调用定义,但是在生产中实际使用它还有很多需要考虑的地方:

  • 获得具有“安全”访问模式的句柄。
  • 适当关闭 native 句柄
  • 代码访问安全 (CAS) 信任级别(仅限 .NET Framework)
  • 路过SecureString当您可以通过用户按键安全地收集一个时。

与其自己编写代码,不如考虑使用我的 SimpleImpersonation库,它提供了一个围绕 LogonUser 的托管包装器获取用户句柄的 API:

using System.Security.Principal;
using Microsoft.Win32.SafeHandles;
using SimpleImpersonation;

var credentials = new UserCredentials(domain, username, password);
using SafeAccessTokenHandle userHandle = credentials.LogonUser(LogonType.Interactive);  // or another LogonType

您现在可以使用 userHandle使用上面第一部分中提到的任何方法。这是 SimpleImpersonation 库 4.0.0 版的首选 API。有关详细信息,请参阅项目自述文件。

远程计算机访问

重要的是要认识到模拟是一个本地机器的概念。不能使用只有远程机器知道的用户来模拟。如果要访问远程计算机上的资源,本地机器和远程机器必须附加到同一个域,或者两台机器的域之间需要有信任关系。如果任何一台计算机都是无域的,则不能使用 LogonUser或 SimpleImpersonation 连接到该机器。

关于c# - 您如何在 .NET 中进行模拟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/125341/

相关文章:

c# - 如何在许多模拟单个 AD 用户帐户的网络 PC 上创建 C# 服务

c# - 单击一次静默更新检查应用程序更新始终检查

c# - 将配置绑定(bind)到 .NET Core 2.0 中的对象图

.net - 为什么 .NET 在调用目录 "Directory"和 "Folder"时不一致?

c# - WPF - 如何从按钮处理程序确定列表框中当前项目的索引

hadoop - Hive 用户模拟

c# - Backgroundworker 不会在 DoWork 方法中执行 extern dll 函数

c# - ORDER BY C# 枚举标志最匹配

c# - .net win 表单(如 asp.net web 表单)中是否有可用的验证控件?

vb.net - 在模拟用户下运行的非 UI 线程是否会自动模拟 UI 线程?