【问题标题】:WCF service dual impersonation?WCF服务双重模拟?
【发布时间】:2012-03-21 17:54:12
【问题描述】:

我的设置有点复杂,所以让我先复习一下。

我们有一个 WCF Web 服务,它通过几个不同的 API 从各种来源获取数据,并将该数据返回给客户端。要求的安全性是通过 HTTPS(工作)完成 IIS 标准是应用程序池必须设置为使用基本的 IIS 网络服务帐户,并且应该使用 .net 模拟。

我的问题是 Web 服务应该始终在 AD 进程 ID 下运行,无论是谁调用它,但它还应该检查调用者所在的 AD 组以确定可以访问哪些功能。现在我可以设置我的 web.config 来使用,这种方法可以让它始终以 Blah 的身份运行,但是我不知道如何让它模拟/检查调用用户以查看他们也可以访问哪些功能。

**edit:忘了提到调用客户端应该能够传递 UN/PASS 而不仅仅是它的 windows 令牌。 wcf 服务应验证其有效的 AD UN 和 PASS 以及轮询它所在的组。

【问题讨论】:

    标签: c# wcf security


    【解决方案1】:

    听起来你想要HostingEnvironment.Impersonate

    例子:

    using (var imp = HostingEnvironment.Impersonate())
    {
        // code now executes in the context of the authenticated user, 
        // rather than the service account
    }
    

    这非常有效,不幸的是这里的标准是不使用应用程序池,因为密码管理对他们来说更容易,如果每个团队都通过将其放入 web.config 来使其保持最新状态

    嗯,这似乎有悖常理,但我这一天遇到过更糟糕的政策,所以我很难判断。 ;)

    正如我在评论中提到的,Impersonate 的重载允许您模拟任意帐户。为此,您必须获取该用户的 Windows 身份令牌,这很重要,据我所知,这不是您可以 100% 在托管代码中执行的操作。您必须使用非托管代码,并且您必须知道应用程序中模拟帐户的用户名和密码。如果您想与网络架构师 BTW 争论这一点,这远不如简单地将帐户设置为 App Pool ID 安全。只是给你一些弹药。

    无论如何,这是我从互联网上改编的一些示例代码:

    #region native imports. 
    public const int Logon_LogonTypeInteractive = 2;
    public const int Logon_ProviderDefault = 0;
    public const int Duplicate_ImpersonationLevelImpersonate = 2;
    
    [DllImport("advapi32.dll")]
    public static extern bool LogonUser(string lpszUserName, string lpszDomain, string lpszPassword,
        int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
    [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    public static extern bool DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);
    
    [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    public static extern bool RevertToSelf();
    
    [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
    public static extern  bool CloseHandle(IntPtr handle);
    #endregion native imports. 
    
    #region elsewhere...
    public IntPtr GetWindowsTokenForImpersonation(string username, string password, string domain)
    {
        IntPtr loginToken = IntPtr.Zero;
        IntPtr workingToken = IntPtr.Zero;
        bool success
        if(!RevertToSelf()) 
        {
            return IntPtr.Zero;
            // failed to eliminate any existing impersonations. This block may not be necessary depending on your code
        } 
        if(!LogonUserA(username, domain, password, Logon_LogonTypeInteractive, Logon_ProviderDefault, ref loginToken))
        {
            return IntPtr.Zero;
            // failed to log in the user
        }
    
        if(!DuplicateToken(loginToken, Duplicate_ImpersonationLevelImpersonate, ref workingToken)
        {
            if(loginToken != IntPtr.Zero)
            {
                CloseHandle(loginToken);
            }
            return IntPtr.Zero;
            // failed to get a working impersonation token
        }
    
        CloseHandle(loginToken);
        return workingToken; // NOTE: You must dispose this token manually using CloseHandle after impersonation is complete. 
    }
    #endregion elsewhere
    
    #region where you want to impersonate
    
    var token = GetWindowsTokenForImpersonation(username, password, domain);
    if(token != IntPtr.Zero)
    {
        using(var imp = HostingEnvironment.Impersonate(token))
        {
            // code here executes under impersonation
        }
        CloseHandle(token);
    }
    #endregion
    

    【讨论】:

    • 我认为我的帖子可能令人困惑。应用程序池 ID 只是基本的 IIS 帐户。我希望始终以“Domain\Serviceaccount1”运行应用程序的进程 ID 是“Domain\User”。 wcf 服务应模拟“Domain\Serviceaccount1”以运行任何功能,但应检查“Domain\User”以确保用户位于正确的组中以运行这些功能。实际的应用程序池 ID 不应用于任何用途。
    • 为什么不将 Serviceaccount1 设置为应用程序池 ID?也就是说,Impersonate 的重载允许您模拟特定帐户。
    • 这非常有效,不幸的是这里的标准是不使用应用程序池,因为密码管理对他们来说更容易,如果每个团队都通过将其放入 web.config 来保持最新状态跨度>
    • 谢谢你给了我很多东西让我玩。我很感激这次故障,并会让你知道结果如何。
    • 我需要在 IIS 中托管的 WCF 服务中调用 Process.Start(MyCommand.exe),有什么建议吗?
    猜你喜欢
    • 2011-02-10
    • 2014-03-06
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-21
    相关资源
    最近更新 更多