【问题标题】:Calling WindowsIdentity.Impersonate does nothing调用 WindowsIdentity.Impersonate 什么都不做
【发布时间】:2012-05-17 00:32:14
【问题描述】:

我正在使用以下Microsoft example。每次 WindowsIdentity 实例调用 .Impersonate() 时,什么都没有发生。没有错误,没有假冒。
在调用前后,当前身份始终是 AppPool 身份。
我还尝试了另一个在网上找到的例子,the Impersonator class,同样的事情也发生了。

我对这些示例所做的唯一修改是在 LogOnUser 调用中将 LOGON32_LOGON_INTERACTIVE 更改为 LOGON32_LOGON_NETWORK,因为使用 Interactive 总是返回 0 错误。

这是一个在 Win2k8 服务器上运行的 ASP.NET 4.0 应用程序,试图在 AD 中模拟用户。

编辑: 我最初没有提到这一点,但我修改了 Microsoft 示例并将其转换为一个类,以便我可以从我的 ASP.NET 应用程序中获得它。我在 web.config 中也有 impersonate=true

【问题讨论】:

  • 您是希望整个 ASP.Net 应用模拟某个用户,还是只想临时模拟另一个用户(例如在方法调用期间)?
  • 暂时...用于文件访问。每个用户登录到应用程序(表单登录)。应用根据应用服务器的 AD 对用户进行身份验证。一般情况下,用户可以在 apppool 身份下运行应用程序。但是,某些用户可能需要文件访问权限。然后我想冒充用户(因为我有他们的登录详细信息)。此外,并非所有用户都拥有服务器上的文件访问权限。

标签: asp.net iis-7.5 impersonation


【解决方案1】:

为用户组授予对 App_Data 文件夹的写入权限解决了该问题。不过不确定这与模仿有什么关系。

【讨论】:

    【解决方案2】:

    我最终找到了一个助手类,我在几年前做过类似的事情。助手实现 IDisposable,因此只需将文件访问代码包装在“使用”中,如下所示:-

    using (Impersonate imp = new Impersonate())
    {
        // Code in here will run under the identity specified in the helper
    }
    

    这里是帮助类的代码(我已经删除了“使用”以节省一些空间)。您会注意到用户帐户在构造函数中是硬编码的:

    internal class Impersonate : IDisposable
    {
        private const int LOGON32_LOGON_INTERACTIVE = 2;
        private const int LOGON32_PROVIDER_DEFAULT = 0;
    
        private bool _disposed = false;
        private WindowsImpersonationContext _context = null;
    
        [DllImport("advapi32.dll")]
        private static extern int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);
    
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool RevertToSelf();
    
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern bool CloseHandle(IntPtr handle);
    
        internal Impersonate()
        {
            WindowsIdentity tempWindowsIdentity;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;
    
            string domain = "<whatever>";
            string username = "<whatever>";
            string password = "<whatever>";
    
            try
            {
                if (RevertToSelf())
                {
                    if (LogonUserA(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                    {
                        if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                        {
                            tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                            _context = tempWindowsIdentity.Impersonate();
                        }
                    }
                }
            }
            finally
            {
                if (token != IntPtr.Zero)
                {
                    CloseHandle(token);
                }
    
                if (tokenDuplicate != IntPtr.Zero)
                {
                    CloseHandle(tokenDuplicate);
                }
            }
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        private void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    // Dispose any managed resources here.
                }
    
                // Stop the impersonation.
                _context.Undo();
    
                _disposed = true;
    
            }
        }
    }
    

    试一试,让我知道你的进展如何......

    安德鲁

    【讨论】:

    • 这与我所拥有的非常相似。问题在于tempWindowsIdentity.Impersonate() 电话。它不会模拟,也不会引发错误。当前身份保持不变。问题必须是服务器/AD 设置或某些权限问题,因为网络上的所有示例都与此类似。还是谢谢。
    • 至少你知道这不是你的代码。听起来像是特权问题。您是否尝试在调用 LogonUser 后遇到最后一个错误(请参阅此处:stackoverflow.com/questions/996429/logonuser-and-delegation)。还可以尝试在服务器上授予您的 ASP.Net 进程帐户“充当操作系统的一部分”权限,并检查您尝试模拟的帐户是否能够登录到服务器。
    【解决方案3】:

    您链接的示例用于控制台应用程序。如果您有一个 ASP.Net Web 应用程序,您希望您的代码在访问者的安全上下文中执行,您可以在 IIS 身份验证设置中启用 ASP.Net 模拟(在 IIS 管理器 MMC 管理单元中)。

    【讨论】:

    • 查看我的编辑...我将控制台应用程序变成了一个类。我主要关心的是实际模仿的细节。
    • 您的情况看起来很像stackoverflow.com/questions/1066275/… 尽管您的情况可能通常倾向于使用 Windows 身份验证而不是表单身份验证(为什么要使用表单?因为登录表单看起来更好?这真的值得吗?你现在花在破解一个基本上不受支持的解决方案上的钱?)还要记住,如下所述的每次模拟都需要完整的用户登录,这可能会使你的网络应用程序变慢...
    • 它是表单,因为用户可以从任何计算机登录。由于用户的要求,登录表单是必要的。
    猜你喜欢
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    相关资源
    最近更新 更多