运行 ServiceHost 时不能同时支持 http 和 https url

Posted

技术标签:

【中文标题】运行 ServiceHost 时不能同时支持 http 和 https url【英文标题】:Cannot support both http and https url when running a ServiceHost 【发布时间】:2018-11-30 16:24:02 【问题描述】:

我正在尝试在HTTPHTTPS 上启用ServiceHost

这是运行服务的代码:

oServiceHost = new ServiceHost(typeof(API), new Uri(WebHookURL))
oServiceHost.Open();

正如您在此处看到的 - 我在运行时获取服务 URL (WebHookURL)。 如前所述,URL 协议可以是HTTPHTTPS

经过大量阅读和测试,最终得到了这个web.config 文件:

 <system.serviceModel>
    <client>
      <endpoint binding="customBinding" bindingConfiguration="encryptingBinding" contract="ModuleComm.Commons.ServiceContracts.ModuleService" name="clientConf" />
    </client>
    <services>
      <service name="myServiceWebServer.AsynchronousSocketListener">
        <endpoint binding="customBinding" bindingConfiguration="encryptingBinding" contract="ModuleComm.Commons.ServiceContracts.ModuleService" />
      </service>
      <service behaviorConfiguration="API.Service1Behavior" name="myServiceWebServer.API">
        <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" contract="myServiceWebServer.IAPI" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="API.Service1Behavior">
          <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp />        
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <customBinding>
        <binding name="encryptingBinding">
          <!--  <messageEncryping /> -->
          <textMessageEncoding>
            <readerQuotas maxStringContentLength="2147483647" />
          </textMessageEncoding>
          <tcpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
            <connectionPoolSettings leaseTimeout="23:59:00" maxOutboundConnectionsPerEndpoint="10000" />
          </tcpTransport>
        </binding>
      </customBinding>
      <webHttpBinding>
        <binding name="webBinding">
          <security mode="Transport">
            <transport clientCredentialType="None"/>
          </security>
        </binding>
      </webHttpBinding>
    </bindings>
    <protocolMapping>
      <add binding="webHttpBinding" bindingConfiguration="webBinding" scheme="https" />
    </protocolMapping>
  </system.serviceModel>

当尝试将 WebHookURL(例如:http://localhost:8111)设置为 http 地址时 - 代码可以正常工作。

不幸的是,当将WebHookURL 设置为https 地址时(例如:https://localhost:8111) - 代码将不起作用,并且在尝试创建ServiceHost实例:

Could not find a base address that matches scheme http for the endpoint with binding WebHttpBinding. Registered base address schemes are [https].

我错过了什么?

更新 1:

尝试了此配置,但出现配置错误: 试过这个,但我收到配置错误:

<system.serviceModel>
    <services>      
      <service behaviorConfiguration="API.Service1Behavior" name="WebServer.API">
        <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="webBinding" contract="WebServer.IAPI" />
        <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="wsBindingHTTPS" contract="WebServer.IAPI" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="API.Service1Behavior">
          <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp />        
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>      
      <wsHttpBinding>        
        <binding name="webBinding">
          <security mode="None">
            <transport clientCredentialType="None"/>
          </security>
        </binding>
        <binding name="wsBindingHTTPS">
          <security mode="Transport">
            <transport clientCredentialType="None"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>

【问题讨论】:

更好的方法是在前面放置一个网络服务器并终止服务器上的 SSL,然后转发请求 【参考方案1】:

问题出在这里:

   <webHttpBinding>
        <binding name="webBinding">
          <security mode="Transport">
            <transport clientCredentialType="None"/>
          </security>
        </binding>
      </webHttpBinding>

webHttpBinding 仅支持 HTTP 请求,不支持 HTTPS 请求。 webHttpBinding 也不支持互操作性。

WsHttpBinding 还支持互操作性。使用此绑定,SOAP 消息默认是加密的。它支持 HTTP 和 HTTPS。在编码方面,它提供了对 Text 以及 MTOM 编码方法的支持。它支持 WS-* 标准,如 WS-Addressing、WS-Security 和 WS-ReliableMessaging。默认情况下,可靠会话被禁用,因为它会导致一些性能开销。 http://www.codeproject.com/Articles/431291/WCF-Services-Choosing-the-appropriate-WCF-binding

所以为了使用 https,请将 webHttpBinding 替换为 WsHttpBinding

这是一个与您的解决方案相匹配的 sn-p:

1) 为服务编写两个端点,一个用于http,另一个用于https。

<services>
    <service behaviorConfiguration="MyServiceBehavior" name="JK.MyService">

      <endpoint address="" behaviorConfiguration="WebBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="JK.IMyService">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>

      <endpoint address="" behaviorConfiguration="WebBehavior" binding="webHttpBinding" bindingConfiguration="webBindingHTTPS" contract="JK.IMyService">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>     

    </service>
  </services>

2) 在 serviceBehaviors 中同时启用 httpGetEnabled="True" httpsGetEnabled="true"。

<behaviors>

<serviceBehaviors>      
  <behavior name="MyServiceBehavior">
    <serviceMetadata httpGetEnabled="True" httpsGetEnabled="true"/>
    <serviceDebug includeExceptionDetailInFaults="true" />
  </behavior>      
</serviceBehaviors>

<endpointBehaviors>
  <behavior name="WebBehavior">
    <webHttp/>
  </behavior>
</endpointBehaviors>

</behaviors>

3) 为http和https编写两个绑定配置。对于 http 给出安全模式 =“None”,对于 https 给出模式 =“Transport”。

<bindings>
    <wsHttpBinding>

      <binding name="webBinding">
        <security mode="None">
          <transport clientCredentialType="None" />
        </security>
      </binding>

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

    </wsHttpBinding>
  </bindings>

检查这个link

【讨论】:

在我将其更改为 wsHttpBinding 后,我在尝试使用 https 时收到此错误:找不到与绑定 WebHttpBinding 的端点的方案 http 匹配的基地址。注册的基地址方案是 [https]。 添加了一个sn-p。 请看一下“UPDATE 1”..还是不行。【参考方案2】:
<services>      
  <service behaviorConfiguration="API.Service1Behavior" name="WebServer.API">
    <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="webBinding" contract="WebServer.IAPI" />
    <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="wsBindingHTTPS" contract="WebServer.IAPI" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>

在上面配置中定义的端点中,绑定的值被指定为webHttpBinding。但是,为这些绑定提供的配置是为wsHttpBinding 定义的。显然,绑定类型与其配置不匹配。以下更改应该可以解决此错误。

<services>      
  <service behaviorConfiguration="API.Service1Behavior" name="WebServer.API">
    <endpoint address="" behaviorConfiguration="web" binding="wsHttpBinding" bindingConfiguration="webBinding" contract="WebServer.IAPI" />
    <endpoint address="" behaviorConfiguration="web" binding="wsHttpBinding" bindingConfiguration="wsBindingHTTPS" contract="WebServer.IAPI" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>

同样在下面的 sn-p 中,transport 元素是多余的,因为安全模式是 None,因此可以删除。

<binding name="webBinding">
  <security mode="None">
    <transport clientCredentialType="None"/>
  </security>
</binding>

【讨论】:

尝试更改为 binding="wsHttpsBinding" 仍然无法正常工作。请注意,我在“UPDATE1”配置中有两种绑定(其中一种是 webHttpBinding)。【参考方案3】:

这是另一个想法:为什么不只允许 HTTPS 请求并将 http 请求重新路由到 https 请求。如果您的 Web 服务器有 IIS,那么您可能会发现 this 很有用

并且可以做bar http请求like

我们通常在 NLB 节点(网络负载平衡)上申请证书,并在所有单独的 Web 服务器上配置 http 到 https 路由

【讨论】:

【参考方案4】:

其实很简单。您只需要一个绑定 http 和另一个绑定 https,如下所示:

<bindings>
 <basicHttpBinding>
    <binding name="SoapBinding"  />
 </basicHttpBinding>
 <mexHttpBinding>
    <binding name="MexBinding" />
 </mexHttpBinding>
 <mexHttpsBinding>
    <binding name="SecureMexBinding" />
 </mexHttpsBinding>
 <basicHttpsBinding>
    <binding name="SecureSoapBinding"  />
 </basicHttpsBinding>
 <webHttpBinding>
    <binding name="RestBinding"  />
    <binding name="SecureRestBinding" >
     <security mode="Transport" />
    </binding>
 </webHttpBinding>
</bindings>
    <services>
        <service behaviorConfiguration="ServiceBehavior" name="myServiceWebServer.API">
            <endpoint address="soap" binding="basicHttpBinding" bindingConfiguration="SoapBinding" name="Soap" contract="myServiceWebServer.IAPI" />
            <endpoint address="soap" binding="basicHttpsBinding" bindingConfiguration="SecureSoapBinding" name="SecureSoap" contract="myServiceWebServer.IAPI" />
            <endpoint address="" behaviorConfiguration="Web" binding="webHttpBinding" bindingConfiguration="RestBinding" name="Rest" contract="myServiceWebServer.IAPI" />
            <endpoint address="" behaviorConfiguration="Web" binding="webHttpBinding" bindingConfiguration="SecureRestBinding" name="SecureRest" contract="myServiceWebServer.IAPI" />
            <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="MexBinding" name="Mex" contract="IMetadataExchange" />
            <endpoint address="mex" binding="mexHttpsBinding" bindingConfiguration="SecureMexBinding" name="SecureMex" contract="IMetadataExchange" />
        </service>
    </services>

【讨论】:

不幸的是 - 在尝试了您建议的配置后,我收到此错误:“找不到与绑定 WebHttpBinding 的端点的方案 https 匹配的基地址。注册的基地址方案是 [http]。” 很简单。我猜你在 iis 上托管了你的应用程序。确保在您的网站上同时添加 HTTP 和 HTTPS 绑定。或者,如果您不需要它们,您可以移除肥皂绑定。

以上是关于运行 ServiceHost 时不能同时支持 http 和 https url的主要内容,如果未能解决你的问题,请参考以下文章

ServiceHost 仅支持类服务类型

mexHttpBinding - 将 ServiceMetadataBehavior 添加到配置文件或直接添加到 ServiceHost 以启用对此协定的支持

WCF:啥是 ServiceHost?

TestNG 数据驱动注解,可配合Grid支持多node机器,多浏览器同时运行脚本

可以在单个ServiceHost中使用多种服务类型和服务端点吗?

如何删除 ServiceHost 持有的大对象堆上的 Byte[]