Как объединить конфигурацию служб WCF для http и https в одном файле web.config? - PullRequest
25 голосов
/ 03 декабря 2010

Я потратил много времени на выяснение того, как настроить мои службы 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>

Я полагал, что установка обеих конечных точек даст две возможности для поиска при активации службы. Тем не менее, это не работает. Я получаю эту ошибку:

Не удалось найти базовый адрес, который соответствует схеме https для конечной точки с привязкой BasicHttpBinding. Схемы зарегистрированных базовых адресов: [http].

Из-за просмотра SO и остального интернета выяснилось, что у других были проблемы с убийством этого дракона.

Ответы [ 3 ]

16 голосов
/ 03 декабря 2010

Хорошо, одна проблема с вашей объединенной конфигурацией состоит в том, что ваши две конечные точки находятся на одном и том же адресе - это не будет работать.

Если вы размещаете в 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>
2 голосов
/ 12 июля 2012

Проблема не в файле конфигурации, а в настройке IIS. Вам нужно включить HTTP и HTTPS в IIS. В IIS 7.5 перейдите на свой сайт и нажмите «Привязки» в разделе «Изменить действие сайта». Убедитесь, что оба http и https были добавлены. Затем вам нужно создать привязку для HTTP в <basicHttpBinding> с режимом безопасности равным none. Добавьте вновь созданную конфигурацию привязки в конечную точку http. Тебе хорошо идти. Дайте мне знать, если вам нужна дополнительная проблема.

0 голосов
/ 29 июня 2018

Решением для запуска в локальном домене, а также для работы в производственных и других средах, не полагаясь на память, чтобы что-либо изменить, является преобразование конфигурации. Они преобразуют скомпилированный файл web.config на основе выбранного профиля конфигурации. Локально я работаю в режиме Debug, в тестовой среде я публикую в профиль TestRelease, и у меня есть другой профиль:

Web.Config Transforms in Visual Studio

Если вы не можете расширить свой файл web.config, вы можете щелкнуть правой кнопкой мыши и добавить изменения конфигурации. Чтобы получить больше, чем Debug и Release, вы добавляете больше конфигураций через менеджер:

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