【问题标题】:How can I combine the WCF services config for both http and https in one web.config?如何将 http 和 https 的 WCF 服务配置合并到一个 web.config 中?
【发布时间】:2011-05-19 19:35:30
【问题描述】:

我花了很多时间弄清楚如何配置我的 WCF 服务,以便它们在生产环境中适用于 https。

基本上,我需要这样做:

<behaviors>
  <serviceBehaviors>
    <behavior name="MyServiceBehavior">
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
<services>
  <service name="MyNamespace.MyService" behaviorConfiguration="MyServiceBehavior">
    <endpoint address="" bindingNamespace="https://secure.mydomain.com" binding="basicHttpBinding" bindingConfiguration="HttpsBinding" contract="MyNamespace.IMyService"/>
  </service>
</services>
<bindings>
  <basicHttpBinding>
    <binding name="HttpsBinding">
      <security mode="Transport">
        <transport clientCredentialType="None"></transport>
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

bindingNamespace 属性添加到端点是使它工作的最后一件事。

但是这个配置在我使用常规 http 的本地开发环境中不起作用。所以我的配置是:

<behaviors>
  <serviceBehaviors>
    <behavior name="MyServiceBehavior">
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
<services>
  <service name="MyNamespace.MyService" behaviorConfiguration="MyServiceBehavior">
    <endpoint address="" binding="basicHttpBinding" contract="MyNamespace.IMyService"/>
  </service>
</services>

这里的不同之处在于我将httpsGetEnabled 属性设置为false,并且我删除了bindingConfiguration 和bindingNamespace。

问题是:我如何创建一个可以同时处理两者的配置块?

我真的很讨厌每次发布时都必须对配置进行大量特殊修改。是的,我知道我可以有一个自动更改值的构建后任务,但如果可能的话,我想合并配置。

我尝试过这样的事情:

<behaviors>
  <serviceBehaviors>
    <behavior name="MyServiceBehavior">
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
<services>
  <service name="MyNamespace.MyService" behaviorConfiguration="MyServiceBehavior">
    <endpoint address="" binding="basicHttpBinding" contract="MyNamespace.IMyService"/>
    <endpoint address="" bindingNamespace="https://secure.mydomain.com" binding="basicHttpBinding" bindingConfiguration="HttpsBinding" contract="MyNamespace.IMyService"/>
  </service>
</services>
<bindings>
  <basicHttpBinding>
    <binding name="HttpsBinding">
      <security mode="Transport">
        <transport clientCredentialType="None"></transport>
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

我认为同时放置两个端点会在激活服务时为其提供两个选项。但是,这不起作用。我收到此错误:

找不到与具有绑定 BasicHttpBinding 的端点的方案 https 匹配的基地址。注册的基地址方案是 [http]。

环顾 SO 和互联网的其他部分,似乎其他人在杀死这条龙时遇到了问题。

【问题讨论】:

  • 您是在 IIS 中托管 WCF 服务,还是自托管??
  • 它们在 ASP.NET Web 应用程序中作为 .svc 文件托管。在开发和生产上都使用 IIS7。
  • @sohtimsso1970:你找到解决办法了吗?
  • @Cristi 不,我必须在 dev 和 prod 之间保持不同的配置。在过去的几年里,我几乎在所有地方都离开了 WCF,所以这个问题已经过时了(至少对我来说)。
  • 实际上它最终对我有用。问题是我在 IIS 中没有设置 http 绑定(在一些测试中将其删除并忘记了)。

标签: web-config wcf wcf-binding


【解决方案1】:

好吧,你的组合配置的一个问题是你的两个端点在同一个地址上——这是行不通的。

如果您在 IIS 中进行托管,那么您的服务器、虚拟目录和所需的 *.svc 文件将确定您的基本地址 - 类似于:

http://yourservername/VirtualDirectory/YourService.svc

如果你想有两个端点,至少其中一个需要定义一个相对地址:

<services>
    <service name="MyNamespace.MyService" 
             behaviorConfiguration="MyServiceBehavior">
       <endpoint 
           address="basic" 
           binding="basicHttpBinding" 
           contract="MyNamespace.IMyService"/>
       <endpoint 
           address="secure" 
           binding="basicHttpBinding" bindingConfiguration="HttpsBinding"  
           contract="MyNamespace.IMyService"/>
    </service>
</services>

在这种情况下,您的 HTTP 端点应该是:

http://yourservername/VirtualDirectory/YourService.svc/basic

以及您的安全 HTTPS 端点:

https://yourservername/VirtualDirectory/YourService.svc/secure

此外:您的安全端点使用 HttpsBinding 配置 - 但您缺少这样的绑定配置 - 您所拥有的只是:

<bindings>
  <basicHttpBinding>
    <binding name="HttpBinding">
      <security mode="None">
        <transport clientCredentialType="None"></transport>
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

你需要添加HttpsBinding配置!!

<bindings>
  <basicHttpBinding>
    <binding name="HttpBinding">
      <security mode="None">
        <transport clientCredentialType="None"></transport>
      </security>
    </binding>
    <binding name="HttpsBinding">
      <security mode="Transport">
          <transport clientCredentialType="Windows" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

【讨论】:

  • 如果我了解端点地址的工作原理,添加这些相对位置会改变访问 URL 的位置。我想在 dev 和 prod 中使用相同的 URL。所以我不想仅仅因为我切换到https就必须在最后添加“基本”或“安全”。你是说否则不可能吗?
  • 您是否找到了在同一端点上启用 HTTP/HTTPS 的解决方案?我处于同样的情况 - 基本上我希望根据代码中的当前请求方案更改绑定配置中的 securityMode 值
  • 这里是一个示例,如何为安全和非安全端点提供相同的 URL stackoverflow.com/questions/4797802/…
  • 这个答案确实有效。对于一个地址,只需删除地址字段或为端点定义相同的地址。
  • 在撰写本文时,通过 http 和 https 运行服务需要两个端点。在某个时候,此问题已得到修复,并且 http 和 https 都可以从同一个端点提供服务。
【解决方案2】:

我最近不得不在 Microsoft Azure 应用服务 (IIS) 中的 HTTP 和 HTTPS 上提供 WCF 3.5 REST (webHttpBinding) 服务。这是一个有趣的......和痛苦的冒险。这是我的发现和我的web.config&lt;system.serviceModel&gt;

注意:这些注意事项适用于在 IIS 10 中使用*.svc (@ServiceHost) 文件运行的 WCF REST Web 服务在 Windows Server 2016 上。这些说明适用于自托管 WCF 服务、非 REST WCF 服务(即 SOAP)或早于 .NET Framework 4.7 的平台。这也不适用于 .NET Core。

  • 升级到 .NET Framework 4.7.2 或更高版本(这只是常识)
  • 最重要的部分是使用&lt;serviceHostingEnvironment&gt; 元素是必不可少的,确保设置了multipleSiteBindingsEnabled="true"
  • 不需要在您的web.config 文件中根本不需要&lt;serviceMetadata&gt; 元素。
    • 显然此元素用于 WSDL 元数据 - 而 RESTful 服务不支持 WSDL。
    • 我指出这一点是因为至少有一些关于文章和 StackOverflow 帖子的热门 Google 搜索结果,人们说这是必需的。那些人是不正确的。
  • 不要在您的 &lt;endpoint address="" 属性中使用绝对 URI - 只需将该属性留空即可。
  • WCF 将检测是否可以同时使用 HTTP 和 HTTPS 访问它,如果在宿主应用程序(即 IIS)没有在其父网站中启用 HTTPS 时 web.config 文件告诉 WCF 接受 HTTPS 连接,则会引发错误.
    • 这出乎我的意料,因为我使用过的所有其他 Web 应用程序平台如果配置为 HTTPS 但父 Web 服务器没有配置,则不会抱怨。
      • 特别是考虑到在这种情况下,WCF 与 .NET 请求管道一起/在其内部运行,并且 ASP.NET 当然不关心 IIS 的网站绑定(因为 ASP.NET 被设计为与父网站绑定无关)
      • 注意:“网站绑定”是指 IIS 网站绑定,不是“WCF 绑定”是一个单独的概念。
  • 要在 Visual Studio 和 IIS Express 中本地工作,请确保父 Web 应用程序项目在“属性”窗口中具有“启用 SSL = True”(与“项目属性”窗口不同(是的,我也尖叫):
  • 在 .NET 4.6.1 中,Microsoft 通过允许省略 &lt;services&gt; 元素并在幕后自动生成来简化 WCF 的配置,但是我在使用双 HTTP+ 的 RESTful 服务时没有得到一致的结果HTTPS 绑定,所以我仍然手动指定我的&lt;services&gt;

TL;DR:

这是我的web.config 文件中的&lt;system.serviceModel&gt; 元素:

<system.serviceModel>
    <services>
        <service name="WcfService1.MainService">
            <endpoint address="" binding="webHttpBinding" contract="WcfService1.IMainService" behaviorConfiguration="myWebBehavior" bindingConfiguration="myWebHttpBindingInsecure" />
            <endpoint address="" binding="webHttpBinding" contract="WcfService1.IMainService" behaviorConfiguration="myWebBehavior" bindingConfiguration="myWebHttpBindingSecure" />
        </service>
        <service name="WcfService1.AnotherService">
            <endpoint address="" binding="webHttpBinding" contract="WcfService1.IAnotherService" behaviorConfiguration="myWebBehavior" bindingConfiguration="myWebHttpBindingInsecure" />
            <endpoint address="" binding="webHttpBinding" contract="WcfService1.IAnotherService" behaviorConfiguration="myWebBehavior" bindingConfiguration="myWebHttpBindingSecure" />
        </service>
        <!--  etc... -->
    </services>
    <behaviors>
        <endpointBehaviors>
            <behavior name="myWebBehavior">
                <webHttp />
            </behavior>
        </endpointBehaviors>
        <serviceBehaviors>
            <behavior>
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <protocolMapping>
        <!-- By default (in machine.config), the 'http' scheme is mapped to 'basicHttpBinding' (SOAP), not 'webHttpBinding' (REST) and the 'https' scheme is not mapped. -->
        <add binding="webHttpBinding" scheme="https" bindingConfiguration="myWebHttpBindingSecure" />
        <add binding="webHttpBinding" scheme="http"  bindingConfiguration="myWebHttpBindingInsecure" />
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <bindings>
        <webHttpBinding>
            <!-- maxReceivedMessageSize="104857600" is 100MiB -->
            <binding name="myWebHttpBindingInsecure" maxReceivedMessageSize="104857600" transferMode="Streamed">
                <security mode="None" />
            </binding>
            <binding name="myWebHttpBindingSecure" maxReceivedMessageSize="104857600" transferMode="Streamed">
                <security mode="Transport" />
            </binding>
        </webHttpBinding>
    </bindings>
</system.serviceModel>

【讨论】:

    【解决方案3】:

    问题不在于配置文件,而在于 IIS 设置。 您需要在 IIS 中同时启用 HTTP 和 HTTPS。 在 IIS 7.5 中,转到您的站点并单击编辑站点操作下的绑定。确保已添加 http 和 https。 然后您需要在&lt;basicHttpBinding&gt; 下为HTTP 创建一个绑定,并将安全模式设置为none。 将新创建的绑定配置添加到 http 端点。 你已准备好出发。如果您需要进一步的问题,请告诉我。

    【讨论】:

    【解决方案4】:

    在本地域中运行以及在生产环境和其他环境中运行,而不依赖于内存来更改任何内容的解决方案是配置转换。他们根据选定的配置文件转换编译的 web.config。在本地我以Debug 模式运行,在测试环境中我publishTestRelease 配置文件,而生产我有另一个配置文件:

    如果您无法扩展您的 web.config,您可以右键单击并添加配置转换。为了获得比 Debug 和 Release 更多的功能,您可以通过管理器添加更多配置:

    以下是转换示例:

    Web.Debug.config

    <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
      <!--...-->
      <system.serviceModel>
        <protocolMapping>
          <add binding="basicHttpBinding" scheme="http" xdt:Transform="SetAttributes" />
        </protocolMapping>
        <bindings>
          <basicHttpBinding>
            <binding xdt:Locator="Match(name)" name="basicHttpBindingConfiguration">
              <security xdt:Transform="Remove">
                <transport xdt:Transform="Remove"/>
              </security>
            </binding>
            <binding xdt:Locator="Match(name)" name="fileTransferBinding">
              <security xdt:Transform="Remove">
                <transport xdt:Transform="Remove"/>
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
      </system.serviceModel>
    </configuration>
    

    Web.Release.config

    <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
      <!--...-->
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" xdt:Transform="Replace"/>
              <serviceDebug includeExceptionDetailInFaults="false" xdt:Transform="Replace"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <protocolMapping>
          <add binding="basicHttpsBinding" scheme="https" xdt:Transform="Replace"/>
        </protocolMapping>
        <bindings>
          <basicHttpBinding>
            <binding xdt:Locator="Match(name)" name="basicHttpBindingConfiguration">
              <security mode="Transport" xdt:Transform="Insert">
                <transport clientCredentialType="None" proxyCredentialType="None" />
              </security>
            </binding>
            <binding xdt:Locator="Match(name)" name="fileTransferBinding">
              <security mode="Transport" xdt:Transform="Insert">
                <transport clientCredentialType="None" proxyCredentialType="None" />
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
      </system.serviceModel>
      <system.webServer>
        <directoryBrowse enabled="false"  xdt:Transform="Replace"/>
      </system.webServer>
    </configuration>
    

    【讨论】:

      猜你喜欢
      • 2015-09-15
      • 1970-01-01
      • 2011-04-18
      • 2014-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多