将 WCF 与负载平衡 (AWS) 一起使用时,安全上下文令牌无效

Posted

技术标签:

【中文标题】将 WCF 与负载平衡 (AWS) 一起使用时,安全上下文令牌无效【英文标题】:Invalid security context token when using WCF with a Load Balance (AWS) 【发布时间】:2014-10-17 08:09:48 【问题描述】:

我有一个托管在 AWS 上的 WCF 应用程序。为了获得更高的可用性,我创建了 WCF 机器的快照并使用此映像启动了另一个实例。

另外,我创建了一个弹性负载平衡 (ELB),将请求路由到这 2 个服务器。

使用我的 WCF 客户端,如果我使用机器的公共 IP 地址,我可以成功连接两台服务器。 但如果我使用 ELB 主机名,我的连接会失败并出现以下错误:

System.ServiceModel.FaultException:消息无法 处理。这很可能是因为该操作 'http://tempuri.org/IService/GetCustomerData' 不正确或因为 消息包含无效或过期的安全上下文令牌或 因为绑定之间存在不匹配。安全上下文 如果服务因以下原因中止通道,则令牌将无效 不活动。防止服务中止空闲会话 过早地增加服务端点的接收超时 绑定。

该错误表明我的安全令牌无效或过期。所以,我检查了发送和接收超时,它已经设置为 10 分钟:sendTimeout="00:10:00"receiveTimeout="00:10:00" (请求通常需要 5-15 秒)

我的出价配置:

<bindings>
  <wsHttpBinding>
    <binding name="wsHttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" useDefaultWebProxy="true">
      <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
      <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="Basic"/>
        <message clientCredentialType="UserName"/>
      </security>
    </binding>
  </wsHttpBinding>
</bindings>

另外,我已经仔细检查了:

ELB 和机器防火墙在端口 80 和 443 上打开。 我的 ELB 配置了正确的证书,并且在端口 443 上有一个侦听器。 我在两台机器上都有一个 IIS Web 服务器。如果我使用 ELB 地址,一切正常。 如果 ELB 路由到一台机器,WCF 工作。如果路由到两台机器,WCF 会失败。

【问题讨论】:

【参考方案1】:

我已经设法通过添加以下参数解决了这个问题:establishSecurityContext="false"

<bindings>
  <wsHttpBinding>
    <binding name="wsHttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" useDefaultWebProxy="true">
      <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
      <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="Basic"/>
        <message clientCredentialType="UserName" 
                 establishSecurityContext="false"/> <!-- this line -->
      </security>
    </binding>
  </wsHttpBinding>
</bindings>

谷歌搜索,我了解到:

当此值设置为 false 时,必须使用非对称加密在每次调用时完成密钥交换和验证。此参数的默认值为true,这意味着第一次调用将创建一个使用非对称加密的安全上下文,但它会被缓存,以后的调用将只使用对称加密,这样更快。

性能考虑:Yaron Naveh

当客户端要连续调用很多次时,最好将此参数设置为true,但是使用负载均衡,调用会被路由到不同的服务器,这样会中断由于令牌无效而导致的消息。因此,您必须禁用此安全上下文功能。

建立安全上下文部分的详细解释:https://msdn.microsoft.com/en-us/library/hh273122(v=vs.100).aspx

【讨论】:

【参考方案2】:

根据您在 ELB 上安装了正确证书的声明,我假设您正在使用 SSL 卸载。这可能是个问题,因为需要使用传输安全配置客户端绑定,但服务将通过端口 80 接收请求,因此需要不同的绑定配置。

但是,当您指定客户端凭据时,WCF 需要传输安全性,因此如果您需要发送客户端凭据,您可能必须关闭 SSL 卸载。

【讨论】:

谢谢 dan,但我没有使用 SSL 卸载。我的客户端、服务器和 ELB 仅使用 HTTPS。我设法找到了解决方案,它与安全上下文有关。我已经在这里发布了答案。

以上是关于将 WCF 与负载平衡 (AWS) 一起使用时,安全上下文令牌无效的主要内容,如果未能解决你的问题,请参考以下文章

WCF 未将所有内核与 Visual Studio 2010 负载测试一起使用

AWS VPC:将 NAT 和 Internet 网关与负载均衡器和私有子网一起使用时的奇怪行为

AWS Beanstalk SSL 负载平衡环境

AWS 使用 Fargate 对 ECS 服务的多个端口进行负载平衡

AWS EC2 上的 Websocket 负载平衡

在负载平衡情况下使用 WCF 4.5 RemoteEndpointMessageProperty 获取客户端 IP 地址