【问题标题】:How do I get a WSE 3.0 web service to impersonate my client's identity?如何获得 WSE 3.0 Web 服务来模拟我的客户身份?
【发布时间】:2010-12-24 21:41:38
【问题描述】:

我有一个基于 WSE 3.0 的 Web 服务,在 IIS 6.0 下的 Windows Server 2003 中运行。我希望 Web 服务进程模拟发送 Web 服务请求的客户端用户,但该服务并未模拟客户端。

Web 应用程序有自己的应用程序池,当前设置为在网络服务标识下运行。 Windows Server 2003 计算机帐户已启用 Active Directory 中的委派(至少根据我的 IT 人员)。服务 WSE 策略(在 wse3policyCache.config 中)如下所示:

<policy name="GeneratedServicesPolicy">
    <kerberosSecurity establishSecurityContext="false" renewExpiredSecurityContext="true" requireSignatureConfirmation="false" messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="true" ttlInSeconds="300">
        <protection>
            <request signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
            <response signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
            <fault signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
        </protection>
     </kerberosSecurity>
     <requireActionHeader />
</policy>

该服务在其 web.config 中包含以下条目(以及其他条目):

<identity impersonate="false"/>
<authentication mode="Windows"/>

为应用程序启用匿名访问(这是必需的,因为服务不使用传输级安全性,消息级是)。机器帐户已注册以下 SPN:

HOST/RD360-2
HOST/rd360-2.mycompany.com

客户端在其 wse3policyCache.config 中有以下内容:

<policy name="KerbClient">
    <kerberosSecurity establishSecurityContext="false" renewExpiredSecurityContext="true" requireSignatureConfirmation="false" messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="true" ttlInSeconds="300">
        <token>
            <kerberos targetPrincipal="HOST/rd360-2.mycompany.com" impersonationLevel="Impersonation" />
        </token>
        <protection>
            <request signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
            <response signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
            <fault signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
        </protection>
    </kerberosSecurity>
    <requireActionHeader />
</policy>

客户端代码如下所示:

static void Main(string[] args)
{
    AddFloatsWSWse client = new AddFloatsWSWse();
    client.SetPolicy("KerbClient");

    double result = client.AddFloats(2.3, 3.2);
    Console.WriteLine("Result was: '" + result + "'");
}

不过,该服务并未冒充我的客户身份。我在服务中使用 log4net,当我要求它在 ASP.NET 跟踪日志中打印出 %username 时,它始终是 NT AUTHORITY\NETWORK SERVICE 而不是客户端用户 ID。有什么我做错了吗?有没有什么地方我可以查看 WSE 是否甚至试图执行模拟并失败?我确实在我的事件日志中看到了以下条目(MYDOMAIN 和 MYUSER 在这里被隐藏了):

Event Type: Success Audit
Event Source:   Security
Event Category: Privilege Use 
Event ID:   576
Date:       12/9/2009
Time:       11:07:16 AM
User:       MYDOMAIN\MYUSER
Computer:   RD360-2
Description:
    Special privileges assigned to new logon:
        User Name:  MYUSER
        Domain:     MYDOMAIN
        Logon ID:       (0x0,0x4B410AE)
        Privileges: SeSecurityPrivilege
                SeBackupPrivilege
                SeRestorePrivilege
                SeTakeOwnershipPrivilege
                SeDebugPrivilege
                SeSystemEnvironmentPrivilege
                SeLoadDriverPrivilege
                SeImpersonatePrivilege

----------------------------------------------------------------------------------

Event Type: Success Audit
Event Source:   Security
Event Category: Logon/Logoff 
Event ID:   540
Date:       12/9/2009
Time:       11:07:16 AM
User:       MYDOMAIN\MYUSER
Computer:   RD360-2
Description:
    Successful Network Logon:
        User Name:  MYUSER
        Domain:     MYDOMAIN
        Logon ID:   (0x0,0x4B410AE)
        Logon Type: 3
        Logon Process:  Kerberos
        Authentication Package: Kerberos
        Workstation Name:   
        Logon GUID: {OBFUSCATED}
        Caller User Name:   -
        Caller Domain:  -
        Caller Logon ID:    -
        Caller Process ID: -
        Transited Services: -
        Source Network Address: -
        Source Port:    -

在我的 WSE 跟踪文件中,我确实看到了:

<processingStep description="Entering SOAP filter Microsoft.Web.Services3.Design.RequireSoapHeaderAssertion+RequireSoapHeaderFilter" />
<processingStep description="Exited SOAP filter Microsoft.Web.Services3.Design.RequireSoapHeaderAssertion+RequireSoapHeaderFilter" />
<processingStep description="Entering SOAP filter Microsoft.Web.Services3.Design.KerberosAssertion+ServiceInputFilter" />
<processingStep description="Exited SOAP filter Microsoft.Web.Services3.Design.KerberosAssertion+ServiceInputFilter" />

所以至少我知道 Kerberos 扩展正在处理我的 Kerberos 标头。

编辑:然后,我的 web 服务使用专有客户端通信库调用使用 SSPI/IWA 的另一台服务器(我们称这第三台服务器为 foo 服务器)。我希望它在第二次调用 foo 服务器时使用客户端的身份。这意味着此客户端通信库使用 foo 服务器的 SPN 和不同的服务调用 AcquireCredentialsHandleInitializeSecurityContext。在这种特殊情况下,foo 服务器实际上与 WSE Web 服务在同一台机器上运行(因此它使用 SPN mycompany/rd260-2)。由于第二个跃点是到同一台机器,我希望它使用 NTLM,但它仍然应该模拟我的 Web 服务客户端的用户身份,不是吗?在 foo 服务器的日志中,我看到它接受连接,使用提供的 IWA 安全上下文并告诉我,基于此安全上下文,连接用户是 rd36-2$,这是机器帐户,因为 WSE Web 服务是在 IIS 中以网络服务身份运行(该身份又与计算机帐户相关联)。在 foo 服务器的日志中,它接收到 IWA 安全上下文后,我最终想查看提交 Web 服务请求的用户的身份。将 foo 服务器移到另一台机器上看看是否对此有影响?

【问题讨论】:

    标签: .net web-services impersonation kerberos wse


    【解决方案1】:

    与 WSE 3 一起使用的 Kerberos 令牌是一种消息级安全机制,仅对客户端进行身份验证。它实际上并没有像在 IWA 中那样更改安全上下文,因此您不会在跟踪日志中注意到任何不同之处。为了真正模拟客户,您必须:

    • &lt;kerberos&gt; 元素上使用impersonationLevel="Impersonation" 在安全令牌上启用模拟(您已经完成了);和
    • 让您的 WebMethod 根据令牌的身份创建 WindowsImpersonationContext

    例子:

    WindowsIdentity identity =
        (WindowsIdentity)RequestSoapContext.Current.IdentityToken.Identity;
    WindowsImpersonationContext impersonationContext = null;
    try
    {
        impersonationContext = identity.Impersonate();
    
        // Perform your work here
        // ...
    }
    finally
    {
        if (impersonationContext != null)
        {
            impersonationContext.Undo();
        }
    }
    

    【讨论】:

    • 感谢您的建议!我在我的问题中添加了更多详细信息,概述了服务执行的工作。在我的跟踪日志中,即使 WSE 框架处理了 Kerberos 令牌,我仍然看到该进程作为 NT Authority\Network Service 运行。但也许,根据您的评论,即使在成功模仿之后,我也不应该期望在日志中看到用户的身份?我想我记得当您通过 IIS 结合模拟执行传输级 IWA 时,您会在跟踪日志中看到客户端的用户身份。这只是 TLS IWA 的不同之处吗?
    • 据我所知,IWA在这里并不重要。 WSE 客户端匿名连接并在消息级别进行身份验证/加密/签名。如果没有记错的话,您将永远不会在跟踪日志中看到模拟用户。仅供参考 - WCF 的 WA 完全不同,微软改变了它,因为 WSE 版本太老套了。
    • 另外,如果完成的工作涉及调用某些支持 SSPI 的专有库,那么库完全有可能尝试从调用者以外的其他地方获取其上下文。正如我所提到的,首先尝试一个非常简单的测试,即在某个文件上设置一个 ACL,并将访问权限授予您要模拟的用户,然后尝试在您的 WebService 方法中访问该文件。
    • 我明白了!关键是我自己实际执行模拟(在从当前肥皂上下文中获取 kerberos 令牌之后)。显然,WSE 框架实际上并不执行模拟,这取决于客户端代码。添加您引用的代码 (WindowsIdentity.Impersonate) 后,我确实在日志中看到了我的真实客户端 ID,并且第 3 方通信库正确地使用该身份进行调用。 Aaron,您能否添加有关 WSE 框架不模拟这一事实的信息,然后我会将您的答案标记为已接受。
    【解决方案2】:

    据我所知,情况是当您尝试进行第二跳时,Kerberos 票证被丢弃。在双跳场景中,Kerberos 票证将在第二跳处丢弃。

    之后您的身份验证将失败,并且不会切换到 NTLM。

    【讨论】:

      猜你喜欢
      • 2011-04-05
      • 2010-11-17
      • 1970-01-01
      • 2011-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多