web-dev-qa-db-ja.com

WCF内のCORSサポートRESTサービス

Windowsサービス内でホストされているWCF RESTサービスがあり、Access-Control-Allow-Origin HTTPヘッダー( [〜#〜]の一部として定義)を送信したいcors [〜#〜] )すべての応答。

私が試みた解決策は、 IDispatchMessageInspector 実装内に次のようなものを含めることでした。

public void BeforeSendReply(ref Message reply, object correlationState)
{
    var httpResponse = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
    if (httpResponse != null)
    {
        // test of CORS
        httpResponse.Headers["Access-Control-Allow-Origin"] = "*";
    }
}

通常はこれで機能しますが、残念ながら私のサービスでも HTTP基本認証 を使用します。つまり、Authorizationヘッダーなしでリクエストが届くと、WCFは自動的に401応答を送信して資格情報を要求します。残念ながら、WCFはこの最初の交換中にIDispatchMessageInspectorを呼び出さないため、Access-Control-Allow-Originヘッダーは最初の交換に追加されません。

ブラウザからサービスを呼び出そうとすると問題が発生します。 CORSは、オリジンドメインがAccess-Control-Allow-Origin応答ヘッダーにリストされているドメインと一致する場合にのみクロスオリジンリクエストを許可するように指定しています(*はすべてのドメインに一致します)。残念ながら、ブラウザがAccess-Control-Allow-Originヘッダーのない最初の401応答を見ると、アクセスが妨げられます( 同一生成元ポリシー による)。

WCFによって自動的に送信される最初の401応答にヘッダーを追加する方法はありますか?

19
Kevin

この男は私の日を救った。

http://blogs.Microsoft.co.il/blogs/idof/archive/2011/07.aspx

いつかウェブページが死んだ場合に備えて、彼のメモのいくつかをここに配置します。 (「あなたの答えはここにあります」というリンクを見つけるのは嫌いですが、リンクは無効になっています。)

<behaviors> 
  <endpointBehaviors> 
    <behavior name="webSupport"> 
      <webHttp /> 
      <CorsSupport /> 
    </behavior> 
  </endpointBehaviors> 
</behaviors> 
<extensions> 
  <behaviorExtensions> 
    <add name="CorsSupport" type="WebHttpCors.CorsSupportBehaviorElement, WebHttpCors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
  </behaviorExtensions> 
</extensions> 
<services> 
  <service name="Service.JSonService"> 
    <endpoint address="http://localhost:8080" behaviorConfiguration="webSupport” binding="webHttpBinding" contract="Service.IJSonService" /> 
  </service> 
</services>

ここで、「WebHttpCors.dll」と呼ばれる彼のダウンロード可能なライブラリを見つける必要があります。

しかし、そこには(上記の)十分なものがあり、解決策への道をグーグル/ビングするのに役立ちます。

(私のシナリオでは)ループに陥っていた部分は、IEは機能していましたが、Firefoxは機能していなかったということです。

私の元のページは次のとおりです。

http://localhost:53692/test/WCFCallTestViaJQ14.htm

だから私のサービスは:

http://localhost:8002/MyWCFService/MyWCFMethodByWebGet?state=NC&city=Raleigh

だから私はローカルホスト<<->>ローカルホストトラフィックを持っていました。

****しかし、ポートは異なっていました。 (53692および8002)****

IEはそれで大丈夫でした。 Firefoxはそれで大丈夫ではありませんでした。

次に、各ブラウザーが.Send()要求を異なる方法で処理することを覚えておく必要があります(つまり、JQUERY内で)。

今ではすべてが理にかなっています。

//JavaScript snipplet from JQuery library

if (window.XMLHttpRequest) {

    returnObject = new XMLHttpRequest();

} else if (window.ActiveXObject) {

    returnObject = new ActiveXObject("Microsoft.XMLHTTP");

} else {

msg = "Your browser doesn't support AJAX!";

}

ここに私が最終的にどこかに私を導いたいくつかのキーワード、私がグーグル/ビンビンしてきたフレーズがあります。

    Result: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.statusText]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: http://localhost:53692/test/WCFCallTestViaJQ14.htm :: HandleJQueryError :: line 326" data: no]


XMLHttpRequest Send "NS_ERROR_FAILURE"

JQuery Ajax WCF Self Hosted CORS JSON

今、あなたは彼のブログを読んで、コードIS何をしているのかを理解する必要があります:

たとえば、彼は言います:

値が「*」の「Access-Control-Allow-Origin」ヘッダー

これはあなたが望むものかもしれないし、そうでないかもしれません。この値(ヘッダー)と他の値(メソッドとオリジン)をより適切に制御したい場合があります。

開発環境は一つです。 (必要なすべての*を使用してください)。

制作は別のものです。これらの値をより差別的なものに微調整することをお勧めします。一言で言えば、セキュリティの観点からCORSが実際に何をしているのかを理解する必要があります。すべてを受け入れる動作を追加するだけではありません。

  allowed-origins: '*'
  allowed-headers: '*'
  allowed-methods: '*'
23
granadaCoder

必要なことを実現するには、HttpModuleを実装して登録することで可能な承認を自分で処理する必要があります...そこで401を発行し、それに加えて必要なhttpヘッダーを発行します...ここにはサンプル実装もありますSO --see WCFへの基本HTTP認証の追加REST service

編集-OPからのコメントの後:

OPのコメントによると、彼はセルフホスティングしているとのことなので、ソリューションはHTTPModuleではなく、実際には IDispatchMessageInspector.BeforeSendReply そして IDispatchMessageInspector.AfterReceiveRequest

承認は「なし」に設定し、IDispatchMessageInspectorでカスタム実装/処理する必要があります。これにより、401を発行するときに任意のヘッダーを追加できます。そうしないと、基本認証を処理するランタイムは、適切な/正の認証の前にIDispatchMessageInspectorを呼び出さないでしょう。

これは機能しますが、これはセキュリティに敏感なコードを自分で実装することを意味するため、適切な実装を確実にするために適切な措置を講じる必要があることに注意してください...

6
Yahia

WCFサービスで呼び出される最初のメソッドに次の行を追加するとうまくいきました。

WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");

次のインポートが必要です

System.ServiceModel.Web;

元の回答についてはこれを参照してください

0
PoomaniGP