web-dev-qa-db-ja.com

WCF WebService / IISファイアウォールの背後にあるホスティングと構成の問題

簡単なWCFWebサービスがあります。 IIS、本番ドメインのデフォルトのWebサイトでホストされています。(ローカルアドレス:10.10.20.100)

デフォルトでは、このデフォルトのWebサイトはポート80の「すべての未割り当て」IP用に設定されていました。ただし、これにより、WCFサービスがサーバーのローカルDNS名を使用してWSDLを生成することに気付きました。つまり、wsdl内のすべてのURIは

http://myserver.subdomain.domain.com/.../...

実稼働環境の内部DNSの知識がないサイトにこのサービスを公開する必要があるため、これは良くありませんでした。そして、この特定のサーバーには外部DNS名がありません。ただの外部IPアドレス...

IIS from "All Unassigned"-> "10.10.20.100"の設定を変更することに成功しました

これにより、サービスはURIを使用してWSDLを生成します

http://10.10.20.100/.../...

これは、サブドメイン内および他のサブドメイン上の他のマシンでは問題ありませんが、ここで行き詰まります。サーバーの外部IPアドレス(1.2.3.4)は、NAT/PAT変換を介してマッピングされるため、サーバーのIP設定で明示的に設定されません(つまり、IP構成の下に表示されません)

したがって、内部アドレスの場合と同じように、IISデフォルトのWebサイトIPアドレスを「すべて未割り当て」->「1.2.3.4」から変更すると、WCFサービスは...

不正な要求(無効なホスト名)

そして、IIS内部IPアドレスで構成されたままにして、取得した外部IPアドレスを介してサービスにアクセスしようとすると

No protocol binding matches the given address 
'http://1.2.3.4/TestService/Service.svc'. Protocol bindings are 
configured at the Site level in IIS or WAS configuration

IIS/WCFに、サーバーで明示的に構成されていない外部IPアドレスを使用してWSDL URIを生成させる方法はありますか?

WCFサービスをウィンドウの外にドロップキックする前に誰かが私を助けてくれます。

27
Eoin Campbell

これは、ホストヘッダーが設定されていないためです。これは非常に一般的な問題のようです。私はいつもそれに遭遇します。生成するURIの構成はありません。サイトのホストヘッダーを調べて、正しいアドレスを検索します。仮想ディレクトリにある場合でも、親(この場合はデフォルトディレクトリ)に移動して、ホストヘッダーを追加する必要があります。

これを行う方法がわからない場合はお知らせください。

8
Joshua Belden

これは古いスレッドですが、実際には、プロジェクトをVS Web DeveloperExpressからWCFサービスを含むMonoDevelopに移行するのに役立ちました。

Webアプリケーションは、次のURLを使用してWCFサービスによって定義されたJavaScriptインターフェイスを要求しました: http://127.0.0.1:8080/path-to-service/service.svc/js 、これにより、エラー:指定されたアドレスに一致するプロトコルバインディングがありません

このスレッドに触発されて、127.0.0.1ではなくlocalhostを使用してサービスにアクセスしたため、問題を修正できました。 http:// localhost:8080/path-to-service/service.svc/js へのリクエストでJavaScriptインターフェースを取得しました。

実際、私のアプリケーションはJavaScriptインターフェイスを含めるために絶対URLを使用しませんでしたが、デフォルトでは、MonoDevelopからアプリケーションを起動すると、127.0.0.1を使用してアプリケーションにアクセスするため、サービスからJavaScriptを含める呼び出しは失敗しました。

XSPの構成ではIPアドレスしか指定できないため、127.0.0.1ではなくlocalhostを使用してMonoDevelopからアプリケーションを起動できなかったため、まだ完全ではありませんが、少なくともそれを回避する方法は知っています。

1
Thomas Bindzus

問題は、ポートまたはIPアドレスを変更した後、使用しているアプリケーションプールを再起動する必要があることです。これは、リサイクルされるまで古い情報が残っているためです。

1
SandroG

IIS7でヘッダーを変更する方法は次のとおりです。また、役立つ場合は、web.configをいくつか配置します。

http://www.sslshopper.com/article-ssl-Host-headers-in-iis-7.html

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />      
    <customErrors mode="Off"></customErrors>
  </system.web> 
  <system.serviceModel>
    <client/>
    <services>
      <service name="WcfService1.Service1"
behaviorConfiguration="MyServiceTypeBehaviors">
        <Host>
        <baseAddresses>
          <add baseAddress="https://pws.sjukra.is/"/>        
        </baseAddresses>
        </Host>
        <endpoint address="https://pws.sjukra.is/Service1.svc"
                  listenUri="/" 
        binding="wsHttpBinding"
        contract="WcfService1.IService1"
        bindingConfiguration="myBasicHttpBindingConfig"/>
        <endpoint contract="IMetadataExchange"
   binding="mexHttpsBinding"                   
   address="mex"/>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="myBasicHttpBindingConfig">
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="Windows" />
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyServiceTypeBehaviors">
          <serviceMetadata httpsGetEnabled="true"/>
          <serviceDebug httpsHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
          <serviceCredentials type="System.ServiceModel.Description.ServiceCredentials">
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfService1.Service1,WcfService1"/>
            <serviceCertificate findValue="pws.sjukra.is" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
              <clientCertificate>
                  <authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck"/>
              </clientCertificate>            
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"></serviceHostingEnvironment>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>
1
Vilhelm

FQDNではなくIPアドレスである必要がありますか? FQDNにスワップし、それをサイトのホストヘッダーに設定してから、

cscript //nologo %systemdrive%\inetpub\adminscripts\adsutil.vbs set W3SVC/1/ServerBindings ":80:hostname.example.com"

次に、アプリプールをリサイクルすると、生成されたWSDLにそのホスト名が生成されます。これにより、メリットが得られます。そのFQDNを内部IPに解決する内部DNSと、ファイアウォールIPに解決する外部DNSを設定すると、同じシステムが変更なしで機能します。

1
blowdart

忍者の暴力を防ぐことができるかもしれません...あなたの問題を理解していれば... ServiceHostにそれを理解させるのではなく、web.configでサービスが使用する完全なアドレスを手動で指定できます。サービスのベースアドレスを設定する必要があります。

 <service behaviorConfiguration="Behaviour1" name="Api.Poll">
    <endpoint address="soap" binding="basicHttpBinding" bindingConfiguration="soapBinding"
      contract="Api.IPoll" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    <Host>
      <baseAddresses>
        <add baseAddress="http://www.mydomain.com/Api" />
        <add baseAddress="http://10.10.20.30/Api" />
      </baseAddresses>
    </Host>
  </service>

この方法を使用すると、サービスは、指定されたベースアドレスとサービス名、および追加のエンドポイントアドレス(存在する場合)を受け入れる必要があります。また、プログラムでベースアドレスを設定するには、カスタムServiceHostFactoryを使用する必要があります。下記参照:

    public class ServiceHostFactory : System.ServiceModel.Activation.ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {                        
        ServiceHost Host;

        Host = new ServiceHost(serviceType, baseAddresses[0]);

        return Host;
    }

最後に、ServiceHostFactoryクラスをビルドしたら、.svcファイルのマークアップを編集してサービスに接続する必要があります。

<%@ ServiceHost Language="C#" Debug="true" Service="Api.Poll" Factory="Api.ServiceHostFactory" CodeBehind="Poll.svc.cs" %>
1
Steve