web-dev-qa-db-ja.com

1つのweb.configでhttpとhttpsの両方のWCFサービス構成を組み合わせるにはどうすればよいですか?

本番環境でhttpsで機能するようにWCFサービスを構成する方法を理解するのに長い時間を費やしました。

基本的に、私はこれを行う必要がありました:

<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を削除したことです。

問題は:両方を処理する1つの構成ブロックを作成するにはどうすればよいですか?

私はリリースを行うたびに設定に特別な変更をたくさん加える必要が本当に嫌いです。はい、値を自動的に変更するビルド後のタスクを作成できることはわかっていますが、可能であれば構成をマージしたいと思います。

私はこのようなものを試しました:

<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>

両方のエンドポイントを配置すると、サービスをアクティブ化するときに探す2つのオプションが得られると考えました。ただし、これは機能しません。私はこのエラーを受け取ります:

BasicHttpBindingをバインドしているエンドポイントのスキームhttpsに一致するベースアドレスが見つかりませんでした。登録されているベースアドレススキームは[http]です。

SOとインターネットの残りの部分を見ると、他の人がこのドラゴンを倒すことに問題を抱えているようです。

27
sohtimsso1970

さて、あなたの組み合わせた設定の1つの問題は、2つのエンドポイントが同じアドレス上にあることです-これは機能しません。

IISでホストしている場合は、サーバー、仮想ディレクトリ、および必要な* .svcファイルによって基本アドレスが決まります。次のようになります。

http://yourservername/VirtualDirectory/YourService.svc

2つのエンドポイントが必要な場合は、少なくとも1つで相対アドレスを定義する必要があります。

<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>
17
marc_s

問題は設定ファイルではなく、IIS設定です。IISでHTTPとHTTPSの両方を有効にする必要があります。IIS 7.5では、サイトをクリックし、[サイトアクションの編集]の下の[バインディング]をクリックします。httpとhttpsの両方が追加されていることを確認します。次に、セキュリティモードを[なし]に設定して、<basicHttpBinding>の下にHTTPのバインディングを作成する必要があります。新しく作成したバインディング構成をhttpエンドポイント。準備完了です。さらに問題が必要な場合はお知らせください。

2
mohit bansal

最近、WCF 3.5 REST(webHttpBinding)サービスをMicrosoft Azure App Service(IIS)のHTTPとHTTPSの両方で利用できるようにする必要がありました。苦しむ冒険。これが私の発見と私のweb.config<system.serviceModel>です。

注:これらの注意事項は、WCFの場合ですREST *.svc@ServiceHost)内で実行されているWebサービス最小のASP.NET 4.7アプリケーション(Global.asax付き)IIS 10 in 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 3.5でのみ必要でした。
    • Microsoftは、IISでWCFをホストする場合、空白のままにする(またはPATH_INFOスタイルのエンドポイントに相対URIを使用する)と言っています:
  • WCFは、HTTPとHTTPSの両方を使用して到達できるかどうかを検出し、web.configファイルが、WCFに親WebサイトでHTTPSが有効になっていないときに、HTTPS接続を受け入れるようにWCFに指示するとエラーを発生させます
    • 私が使用した他のすべてのWebアプリケーションプラットフォームは、HTTPS用に構成されていても、親Webサーバーは構成されていないと文句を言わないので、これは私には予想外でした。
      • 特にこの場合、WCFは.NETリクエストパイプラインの内部または内部で実行され、ASP.NETはIISのWebサイトバインディングを気にしません(ASP.NETは親のWebサイトバインディングを認識しないように設計されているため)。
      • 注:「Webサイトバインディング」とは、別の概念であるIIS Webサイトバインディング、ではない「WCFバインディング」)を指します。
  • これをVisual StudioおよびIIS Expressでローカルに機能させるには、親Webアプリケーションプロジェクトの[プロパティ]ウィンドウで "SSL Enabled = True"が設定されていることを確認してください( "Projectプロパティ」ウィンドウ(はい、私も悲鳴を上げました):
    • enter image description here
  • .NET 4.6.1では、Microsoftは<services>要素を省略して自動的に舞台裏で生成できるようにすることでWCFの構成を簡素化しましたが、デュアルHTTP + HTTPSのRESTfulサービスで一貫した結果が得られませんでしたバインディングなので、引き続き<services>を手動で指定します。

TL; DR:

これが私の<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>
1
Dai

ローカルドメインで実行し、本番環境やその他の環境でも実行するためのソリューションは、メモリを変更することなく変更を行う構成変換です。選択した構成プロファイルに基づいて、コンパイル済みのweb.configを変換します。ローカルでDebugモードで実行し、テスト環境で publishTestReleaseプロファイルに、本番環境に別のプロファイルを持っています。

Web.Config Transforms in Visual Studio

Web.configを展開できない場合は、右クリックして構成変換を追加できます。デバッグとリリース以上のものを取得するには、マネージャーを介して構成を追加します。

Configuration Manager in Visual Studio

次に変換の例を示します。

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>
0
Aske B.