如何使用Windows凭据将WCF服务重定向到HTTPS端点

如何使用Windows凭据将WCF服务重定向到HTTPS端点,wcf,redirect,ssl,windows-authentication,Wcf,Redirect,Ssl,Windows Authentication,以下是我试图处理的情况: 我们有一个WCF客户端,它可以与http端点和https端点一起工作,但当它从http重定向(302)到https时就不能工作。我们有一个F5负载平衡器,它正在执行重定向和SSL功能,但据我所知,它没有做任何请求意外的事情。当WCF不希望在执行重定向后提供Windows Kerberos身份验证信息时,重定向似乎是罪魁祸首 成功调用的顺序(即没有重定向的http)如下所示: <system.serviceModel> <serviceHosti

以下是我试图处理的情况:

我们有一个WCF客户端,它可以与http端点和https端点一起工作,但当它从http重定向(302)到https时就不能工作。我们有一个F5负载平衡器,它正在执行重定向和SSL功能,但据我所知,它没有做任何请求意外的事情。当WCF不希望在执行重定向后提供Windows Kerberos身份验证信息时,重定向似乎是罪魁祸首

成功调用的顺序(即没有重定向的http)如下所示:

<system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <services>
        <service behaviorConfiguration="MyServiceBehavior" name="MyService">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="securedBinding" contract="Contracts.IMyService">
            </endpoint>
        </service>
    </services>
    <bindings>
        <basicHttpBinding>
            <binding name="securedBinding">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Windows" proxyCredentialType="Windows"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="MyServiceBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="true"/>
                <useRequestHeadersForMetadataAddress>
                    <defaultPorts>
                        <add scheme="http" port="80" />
                        <add scheme="https" port="443" />
                    </defaultPorts>
                </useRequestHeadersForMetadataAddress>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>
  • 客户端-使用http方案发送POST服务请求
  • 服务器-以401未经授权的方式响应
  • 客户端-通过授权发送协商帖子
  • 服务器-以100继续响应
  • 客户端-发送soap数据并成功完成
当呼叫被重定向并且失败时,它是这样的:

<system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <services>
        <service behaviorConfiguration="MyServiceBehavior" name="MyService">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="securedBinding" contract="Contracts.IMyService">
            </endpoint>
        </service>
    </services>
    <bindings>
        <basicHttpBinding>
            <binding name="securedBinding">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Windows" proxyCredentialType="Windows"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="MyServiceBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="true"/>
                <useRequestHeadersForMetadataAddress>
                    <defaultPorts>
                        <add scheme="http" port="80" />
                        <add scheme="https" port="443" />
                    </defaultPorts>
                </useRequestHeadersForMetadataAddress>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>
  • 客户端-使用http方案发送POST服务请求
  • 服务器-返回302并重定向到同一地址的https方案
  • 客户端-为https地址发送GET(我不明白为什么这是GET而不是POST)
  • 服务器-以401未经授权的方式响应
  • 客户端-引发异常“HTTP请求未经客户端身份验证方案“协商”授权。从服务器收到的身份验证标头为“协商,NTLM”
它类似于但不完全相同(虽然它确实引用了“打破WCF协议”,但实际上没有一个答案,我可以在上面找到文档)。如果我们关闭F5重定向规则,http和https流量就可以正常工作。WCF真的不能处理这个简单的重定向吗?是否有关于此缺陷的解决方法或任何文档

客户端配置(请注意,在使用https进行测试时,我将TransportCredentialOnly更改为Transport):


服务器配置如下所示:

<system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <services>
        <service behaviorConfiguration="MyServiceBehavior" name="MyService">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="securedBinding" contract="Contracts.IMyService">
            </endpoint>
        </service>
    </services>
    <bindings>
        <basicHttpBinding>
            <binding name="securedBinding">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Windows" proxyCredentialType="Windows"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="MyServiceBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="true"/>
                <useRequestHeadersForMetadataAddress>
                    <defaultPorts>
                        <add scheme="http" port="80" />
                        <add scheme="https" port="443" />
                    </defaultPorts>
                </useRequestHeadersForMetadataAddress>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

我不明白为什么这是一个GET而不是POST

这就是你问题的原因。在收到对POST的302响应后,客户机获得新URL的行为是正常的。见以下网址:

如果302状态代码是响应GET或HEAD以外的请求而接收的,则除非用户能够确认,否则用户代理不得自动重定向请求,因为这可能会改变发出请求的条件

此外,以下SO帖子提供了一些好信息:


所以WCF正在做它应该做的事情,在302重定向后拒绝重新发布。不幸的是,除了第一次正确指定协议以避免302之外,我不确定如何解决您的问题。

我只是做了类似的事情,我可以确认这不起作用。更糟糕的是,如果不替换默认的WCF HTTP传输实现,则可能无法进行更改

重定向和身份验证都直接在WCF的内部HTTP处理中处理。如果永久移动301并且WCF在重定向后不使用配置的客户端凭据,则无法手动处理重定向,这会导致问题


重定向后发送GET而不是POST的问题理论上应该通过返回307临时重定向而不是302 FOND来解决。

这肯定解释了GET,但似乎WCF应该能够处理此切换。也许在其内部,WCF只会在一篇文章上发表评论?比如,框架的这一部分可能没有正确实现?通过某种方式确定是很好的。401未经授权是否包含适当的WWW身份验证标头?两者都是401(有重定向和没有重定向是相同的。我很确定我们尝试过这个,WCF不理解响应。我希望在4.5中有办法解决这个问题,但我还没有研究过。可能是重复的