WCF路由Https引发来自托管路由器的服务的多个请求

时间:2012-02-16 20:47:58

标签: .net wcf c#-4.0 wcf-security wcf-routing

我有一个场景,我需要使用基本身份验证连接到安全的外部soap Web服务。通常这不是问题,这可以在我的本地开发环境中使用basicHttpBinding。当应用程序部署时,它将存在于DMZ中,并且无法访问呼叫世界。这在我们的内部网络上创建了对路由服务的需求,并且WCF 4.0中的新路由功能似乎是一个很好的候选者。我让代码工作通过路由服务作为PoC通过http拨打到不同的外部服务,然后决定进入https。我很快发现初始调用应用程序的用户名凭据不会被路由服务传递,因此我实现了一个自定义IEndpointBehavior,以便将适当的凭据添加到路由服务调用到外部客户端。这是我的客户端应用程序的绑定,以及我的路由服务。

客户端应用:

<basicHttpBinding>
    <binding name="SimpleHttp">
        <security mode="Transport">
            <transport clientCredentialType="Basic"/>
        </security>
    </binding>
</basicHttpBinding>

<endpoint address="https://mymachine/routingservice.svc"
          binding="basicHttpBinding" 
          contract="TheContract" 
          name="MyEndpoint" 
          bindingConfiguration="SimpleHttp"/>

路由服务(服务端点):

<services>
    <service behaviorConfiguration="routingConfiguration"
          name="System.ServiceModel.Routing.RoutingService">
        <endpoint address=""
              binding="basicHttpBinding"
              name="RoutingServiceEndpoint"
              contract="System.ServiceModel.Routing.IRequestReplyRouter"/>
    </service>
</services>

<basicHttpBinding>
    <binding>
        <security mode="Transport">
            <transport clientCredentialType="None"/>
        </security>
    </binding>
</basicHttpBinding>

<serviceBehaviors>
    <behavior name="routingConfiguration">
        <!-- leaving out the filter details for now, since it's match all -->
        <routing filterTableName="filterTable1" />
    </behavior>
</serviceBehaviors>

路由服务(客户端端点):

<client>
    <endpoint name="realDestination"
              address="https://externalwebservice/service/"
              binding="basicHttpBinding"
              bindingConfiguration="otherBasicHttpBinding"
              behaviorConfiguration="CredWriter"
              contract="*" />
</client>

<basicHttpBinding>
    <binding name="otherBasicHttpBinding">
        <security mode="Transport">
            <transport clientCredentialType="Basic"/>
        </security>
    </binding>
</basicHttpBinding>

<endpointBehaviors>
    <behavior name="CredWriter">
        <soapProcessing processMessages="false"/>
        <myCredentialAdder/>
    </behavior>
</endpointBehaviors>

<extensions>
    <behaviorExtensions>
        <add name="myCredentialAdder" type="Assembly Info here."/>
    </behaviorExtensions>
</extensions>

假设我没有遗漏任何明显的东西,这应该都可以工作,并且顺利地通过https将信息从客户端传递到路由器到路由器再到外部服务。 (大假设)

相反,我遇到了以下异常和堆栈跟踪:

System.ServiceModel.CommunicationException: 
An error occurred while receiving the HTTP response to https://mymachine/routingservice.svc. 
This could be due to the service endpoint binding not using the HTTP protocol. 
This could also be due to an HTTP request context being aborted by the server 
(possibly due to the service shutting down). 
See server logs for more details. ---> 
System.Net.WebException: The underlying connection was closed: 
An unexpected error occurred on a receive. ---> 
System.IO.IOException: Unable to read data from the transport connection: 
An existing connection was forcibly closed by the remote host. ---> 
System.Net.Sockets.SocketException: 
An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.Security._SslStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security._SslStream.StartReading(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security._SslStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.TlsStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception stack trace ---

Server stack trace: 
   at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   //calls to my code were here.

看到这一点,我再挖了一下,然后通过Fiddler把所有东西都用来看看发生了什么。

我的客户端应用程序通过https调用我的IIS托管路由服务,然后等待。 IIS托管的路由服务调用外部服务。这是事情变得奇怪的地方。有一个https 200,它显示一个新的'实体'在肥皂信封中返回,另一个https 200也从服务中返回另一个新的'实体',然后我的客户端应用程序调用得到一个504网关超时几乎第二个请求从外部服务返回的确切时间。

此设置为我提供了一个新例外:

System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:59.5720000. 
Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. 
The time allotted to this operation may have been a portion of a longer timeout. 
---> System.TimeoutException: The remote server returned an error: (504) Gateway Timeout. 
---> System.Net.WebException: The remote server returned an error: (504) Gateway Timeout.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception stack trace ---
   at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   --- End of inner exception stack trace ---

Server stack trace: 
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   //calls to my code

我尝试将超时设置为异常建议,但这不起作用,因为这在一两秒内失败,而不是几分钟。因此,在搜索互联网寻找这个问题的示例和其他解决方案之后的这一点上,我找不到任何可以解决为什么会失败的问题,可能存在的问题是什么,或者是否有人试图实现相同的目标。的事情。

我希望您,社区,能够找到我尚未找到的东西,已经自己解决了这个问题并且愿意分享解决方案,或者可以轻松发现我的绑定问题或设置。

0 个答案:

没有答案