WCF、メタデータ、BIGIP-WSDLアイテムの正しいURLを強制できますか?
質問
ServerAでホストされているWCFサービスがあります。これは、インターネットに直接アクセスできないサーバーであり、インターネット以外のルーティング可能なIPアドレスを持っています。
サービスは、SSL暗号化および復号化を処理し、暗号化されていない要求を特定のポートでServerAに転送するBIGIPによって処理されます(現時点では実際には負荷分散を行いませんが、今後追加される可能性があります) 。
それは、クライアントが https://www.OurDomain.com/ServiceUrlを介してサービスを呼び出すことを意味しますそして、BIGIPデバイスを介して http:// SeverA:85 / ServiceUrl のサービスにアクセスします。
https://www.OurDomain.com/ServiceUrl で公開されているWSDLを参照するときWSDLに含まれるアドレスは、 http:// SeverA:85 / ServiceUrl ベースアドレス
に基づいています。ホストヘッダーの設定を使用してドメインを設定できることがわかりましたが、問題は、これによりドメインが整理される一方で、間違ったスキームが使用されることです– Httpsである必要がある間は、 http://www.OurDomain.com/ServiceUrl を使用します。
また–そのサーバーでホストされている他のサービス(asmxベース)があるため、ホストヘッダーの設定で問題が発生したため、サーバー上に別のサイトを作成して(たとえばポート82を使用)、ホストヘッダーを設定できると考えましたその上で現在、http / httpsの問題に加えて、WSDLのすべてのURLにポート番号が含まれているため、BigIPがポート443(SSLの場合)で動作するため、問題があります
ホストヘッダーを実装するよりも柔軟なソリューションはありますか?理想的には、柔軟性とサポートの容易さを維持する必要があります。
ご協力ありがとうございます…
解決
これは本質的に複数の部分からなる問題であり、完全な答えを提供するために多数の個別の解決策が必要です。基本的に、F5の後ろに座るには3つの問題があります。
- アドバタイズされたサービスエンドポイントのホスト名。
- データコントラクトを記述するxsd:import'edスキーマへのリンクのホスト名
- 説明するhttp / httpsの問題。
1と2の解決策を見つけたので、ホストヘッダーを変更します(ホストヘッダー以外の方法でこれにアプローチできますが、ここで説明する必要はありません)。 3番はもう少しトリッキーで、より多くのコードを必要とします(ここでダンプするには多すぎます)。
簡単な答えは、IContractBehaviorとIWsdlExportExtensionの両方を実装するContractBehaviorを記述する必要があるということです。
実装する必要がある重要なビットは、IWsdlExportExtension.ExportEndpointです。このメソッド内では、すべてのWsdlPort拡張機能を反復処理する必要があり、SoapAddressBinding型の拡張機能を見つけた場合、SoapAddressBinding.Locationプロパティをhttpsプロトコル指定子を含む新しいUriに置き換える必要があります。また、xsdインポートアドレスとスキーマリンクに対して同様のビットを実行する必要があります。
サービスでWS-Addressingも使用している場合は、wsdlに書き込む追加のアドレスを処理するために同様の操作を行う必要があります。
最終的には、CodePlexで利用可能なWsdlExtrasプロジェクト( http:// wcfextras。 codeplex.com/ )。 WsdlExtrasで使用されるメソッドは、追加する必要がある余分なビットの優れた基盤を提供します(メモリからは、WS-Addressingビットを扱っていないと思います)。ご覧になりたいのは、「SOAPアドレスの場所のURLをオーバーライドする」です。
他のヒント
Mark Allansonのおかげで、yossi dahanとまったく同じシナリオがありました。WCFExtras.dllファイルは私のために働きました
ステップ1。 WCFExtras.dll (http://www.codeplex.com/WCFExtras/)をダウンロードします。
ステップ2。プロジェクトへの参照を追加します。
ステップ3。サンプルサーバーアプリで提案されているコードを書くことに時間を無駄にしないでください。
ステップ4。 web.configを開き、以下のコードを配置します。
<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing="true" />
</settings>
</system.net>
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceBehaviorName" name="ServiceName">
<endpoint address="" behaviorConfiguration="ServiceEndpointBehaviorName" binding="basicHttpBinding" contract="IServiceName">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="ServiceEndpointBehaviorName">
<wsdlExtensions location="https://sslLoadBalancer/ServiceName.svc"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviorName">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<!-- Declare that we have an extension called WSDL Extras-->
<add name="wsdlExtensions" type="WCFExtras.Wsdl.WsdlExtensionsConfig, WCFExtras, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
ステップ5。また、このURL &quot; https://sslLoadBalancer/ServiceName.svc"
で参照を追加する場合は機能しないことに注意することも重要です。参照は必ず&quot; https ://sslLoadBalancer/ServiceName.svc?wsdl&quot;
を使用すると、アプリケーションに参照を追加できます。
それで...まだ動作しない場合は、知らせて、web.configファイル全体を貼り付けます。
ありがとう
既存のサービスの上にSSLを追加する場合、WCFクライアントのバインディングのセキュリティモードにも影響を与える可能性があり、簡単にオーバーライドできます。
WSDLの場合、ファイルをダウンロードし、URLを必要なものに変更し、ファイルとして手動で公開してみませんか?
エンドポイントのアドレス属性をWSDLに表示したいURLに設定し、リスンする実際のUriを使用してlistenUri属性をエンドポイントに追加するとうまくいくという素晴らしいヒントを得ました。
テストページのUrlは影響を受けません(つまり、ListenUriで指定されたアドレスが引き続き表示されます)が、WSDL内では正しいUri(アドレスで指定されたもの)が設定されます。
最も面倒なことですが、質問を投稿してすぐにこれを試してみたところ、IIS内で動作するようにできませんでした。コンソールアプリでセルフホスティングしているときだけです。今日自分自身をチェックすると、実際に機能することがわかりました。だから今はなぜ以前はうまくいかなかったのか分かりません;
その間に行ったのは、構成からWSDLに必要なアドレスを入れてサービス記述を変更した単純なカスタム動作です。もちろん、そのためのサポートが組み込まれている場合は、はるかに優れているので、来週はこれをさらに調査する時間があるといいのですが。
サービスクラスに属性を追加します。
<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)>
これにより、クライアントはサービスをhttps:// ...としてアドレス指定できますが、サービスはhttp:// .....でホストされます
サービスホストのweb.configでは、エンドポイント要素のアドレス属性に、クライアントが使用するパブリックURLの絶対URLが含まれている必要があります。同じエンドポイント要素で、listenUri属性をサービスホストがリッスンしている絶対URLに設定します。ホストがリッスンしている既定の絶対URIを決定する方法は、サービスがホストされている物理サーバーを指すクライアントアプリケーションにサービス参照を追加することです。クライアントのweb.configには、サービスのアドレスが含まれます。それをホストweb.configのlistenUri属性にコピーします。
サービスの動作設定で、属性httpGetEnabled = trueを持つ要素serviceMetaDataを追加します
だから次のようなものがあります:
<serviceBehaviors>
<behavior name="myBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior
</serviceBehaviors>
...
<services>
<service name="NamespaceQualifiedServiceClass" behavior="myBehavior" >
<endpoint address="https://www.sslloadbalancer.com" binding="someBinding" contract="IMyServiceInterface" listenUri="http://www.servicehost.com" ... />
</service>
</services>
これがメッセージセキュリティとトランスポートセキュリティのどちらで機能するかわかりません。この特定のアプリケーションでは、資格情報はDataContractの一部として渡されたため、basicHttpBindingセキュリティモード=なしになりました。トランスポートは安全であるため(SSLロードバランサーに対して)、セキュリティ上の問題はありませんでした。
listenUri属性を空白のままにすることも可能ですが、存在する必要があります。
残念ながら、WSDLにインポートされたスキーマのベースアドレスがパブリックベースアドレス(エンドポイントのアドレス属性を使用して構成されたもの)ではなくlistenUriベースアドレスを持つというWCFのバグがあります。この問題を回避するには、インポートしたスキーマをWSDLドキュメントに直接取り込み、インポートを削除するIWsdlExportExtension実装を作成する必要があります。この例は http://winterdom.com/2006/10/inlinexsdinwsdlwithwcf で提供されています。 。さらに、サンプルクラスにBehaviorExtensionElementを継承させ、次の2つの新しいメソッドを完了することができます。
Public Overrides ReadOnly Property BehaviorType() As System.Type
Get
Return GetType(InlineXsdInWsdlBehavior)
End Get
End Property
Protected Overrides Function CreateBehavior() As Object
Return New InlineXsdInWsdlBehavior()
End Function
これにより、.configファイルに拡張機能の動作を追加し、サービスファクトリを作成する代わりに構成を使用して動作を追加できます。
system.servicemodel構成要素の下に追加:
<endpointBehaviors>
<behavior name="SSLLoadBalancerBehavior">
<flattenXsdImports/>
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<!--The full assembly name must be specified in the type attribute as of WCF 3.5sp1-->
<add name="flattenXsdImports" type="Org.ServiceModel.Description.FlattenXsdImportsEndpointBehavior, Org.ServiceModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
そして、behaviorConfiguration属性を使用して、エンドポイント構成で新しいエンドポイントの動作を参照します
<endpoint address="" binding="basicHttpBinding" contract="WCFWsdlFlatten.IService1" behaviorConfiguration="SSLLoadBalancerBehavior">