如何在一个web.config中组合http和https的WCF服务配置?

soh*_*970 26 wcf web-config wcf-binding

我花了很多时间搞清楚如何配置我的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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

这里的区别是我将httpsGetEnabled属性设置为false,并删除了bindingConfiguration和bindingNamespace.

问题是:如何创建一个处理BOTH的配置块?

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

我试过这样的事情:

<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>
Run Code Online (Sandbox Code Playgroud)

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

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

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

mar*_*c_s 18

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

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

http://yourservername/VirtualDirectory/YourService.svc
Run Code Online (Sandbox Code Playgroud)

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

<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>
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您将拥有HTTP端点:

http://yourservername/VirtualDirectory/YourService.svc/basic
Run Code Online (Sandbox Code Playgroud)

和您的安全HTTPS端点:

https://yourservername/VirtualDirectory/YourService.svc/secure
Run Code Online (Sandbox Code Playgroud)

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

<bindings>
  <basicHttpBinding>
    <binding name="HttpBinding">
      <security mode="None">
        <transport clientCredentialType="None"></transport>
      </security>
    </binding>
  </basicHttpBinding>
</bindings>
Run Code Online (Sandbox Code Playgroud)

你需要添加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>
Run Code Online (Sandbox Code Playgroud)

  • 如果我了解端点地址的工作方式,那么添加这些相对位置会改变访问URL的位置.我想在dev和prod中使用相同的URL.所以我不想在最后添加"基本"或"安全"因为我切换到https.你是说这不可能吗? (4认同)
  • 您是否找到过在同一端点上启用HTTP/HTTPS的解决方案?我处于相同的情况 - 基本上我希望根据代码中的当前请求方案更改绑定配置中的securityMode值 (4认同)
  • 以下是如何为安全和非安全端点提供相同URL的示例http://stackoverflow.com/questions/4797802/deploying-wcf-service-with-both-http-and-https-bindings-endpoints (4认同)
  • 这个答案实际上有效.对于一个地址,只需删除地址字段或为端点定义相同的地址. (2认同)
  • 在撰写本文时,使服务通过http和https运行需要两个端点。在某个时候,此问题已得到修补,并且可以从同一端点提供http和https。 (2认同)

Dai*_*Dai 5

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

注:这些说明适用于使用WCF REST Web服务上运行*.svc@ServiceHost)最小的ASP.NET 4.7应用程序中的文件(Global.asaxIIS 10中在Windows Server 2016上)这些说明适用于自托管的WCF服务,非REST WCF 服务(即 SOAP)或早于 .NET Framework 4.7 的平台。这也不适用于 .NET Core。

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

特尔;博士:

这是<system.serviceModel>我的web.config文件中的元素:

<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>
Run Code Online (Sandbox Code Playgroud)