23

.NET 4 で asp.NET WCF を使用しています。このサービスは、ユーザーの認証に使用されます。ユーザー名とパスワードを送信すると、認証 Cookie を含む HTTP ヘッダーが返されます。ローカルでホストされているテスト ページを使用すると、これは正しく機能しています。現在、クロスドメインのヘッダー情報にアクセスしようとしています。テスト ページを別のマシンにインストールし、WCF を呼び出すように構成しました。通話は機能しており、通話の「データ」応答は正しいです。ただし、次のいずれかでヘッダー情報にアクセスできません。

alert(xmlHttp.getAllResponseHeaders());

また

alert(xmlHttp.getResponseHeader("Set-Cookie"));

IE のデバッガーと Firefox の「ライブ HTTP ヘッダー」プラグインを使用すると、ヘッダー情報が返されていることがわかります。

グローバル ajax ページで、CORS を処理するように応答を設定しています。

private void EnableCrossDomainAjaxCall()
{
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");


    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {

        HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");

        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    }

}

これは、サービスを呼び出すために使用している AJAX です。

$("#btnLogin").click(function(e) {
    var geturl;
    geturl = $.ajax({
        // type: "POST",
        type: "GET",
        contentType: "application/json; charset=utf-8",
        url: 'http://10.0.4.66/AuthenticationService.svc/Login?Name=test&password=pwsd',
        // url: '../SecurityServer/AuthenticationService.svc/Login?Name=test&password=pwsd',
        dataType: "jsonp",
        error: function(request, status, error) {
            alert('Error Occured');
        },
        crossdomain: true,
        success: function(data, textStatus, xmlHttp) {
            // alert(xmlHttp.getResponseHeader("Content-Type"));
            document.write(xmlHttp.getResponseHeader("Content-Type") + "<br/>");
            alert(xmlHttp.getAllResponseHeaders());
            alert(xmlHttp.getResponseHeader("Set-Cookie"));
            var headers = '';
            var headerPair = xmlHttp.getAllResponseHeaders('wcfCookie').split("\r\n");
            var output = '';
            $.each(headerPair, function(key, line) {
                var parts = line.split(':');

                if (parts[0] == 'wcfCookie') {
                  ChocChip = parts[1]
                  return false
                }

            });
        }
    });

以下は、「ライブ HTTP ヘッダー」から取得したヘッダー情報です。

Date: Mon, 04 Feb 2013 12:12:40 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 4.0.30319
Access-Control-Allow-Origin: *
Set-Cookie: wcfCookie=8D38D5D6A0F138FEB595DD016F7694EDDF3E6757C82ED3D419F5047A5294974C1885487465CEC0A0BCC2B3802C7B03FF9F5370A05D4CCBDDDABCB1558C3816044BF4F78209BF38C6B1A7CAD34CD3C85C40B8515CFB1C2B2694BC78803D8DACB4
Content-Length: 65
Cache-Control: application/json; charset=utf-8
Content-Type: application/x-javascript
4

2 に答える 2

68

まず、少し背景を説明します。

クライアントが送信できる要求ヘッダーAccess-Control-Allow-Headersを指定するを使用していますが、クライアントが読み取ることができる応答ヘッダーを指定していません。クライアントが単純でない応答ヘッダーを読み取れるようにするには、 を使用する必要があります。HTML5 Rocks CORS ページから:Access-Control-Expose-Headers

CORS リクエスト中、getResponseHeader()メソッドは単純なレスポンス ヘッダーにのみアクセスできます。単純な応答ヘッダーは次のように定義されます。

  • キャッシュ制御
  • コンテンツ言語
  • コンテンツ タイプ
  • 期限切れ
  • 最終更新日
  • プラグマ

クライアントが他のヘッダーにアクセスできるようにする場合は、Access-Control-Expose-Headersヘッダーを使用する必要があります。このヘッダーの値は、クライアントに公開する応答ヘッダーのカンマ区切りのリストです。

したがって、その新しい情報が与えられた場合、次のようにすることができます。

HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "Set-Cookie");

...しかし、それだけではありません。

さて、実際の答え:

ここには、もう 1 つの深刻な問題があります。XHR 仕様では、明示的に read を禁止していますSet-Cookie。これは、機能的にクロスドメイン Cookie 盗用攻撃であるためです。

ドメイン A がドメイン B に対してクロスドメイン リクエストを行うとします。ドメイン B が Cookie を設定すると、ドメイン B のみにドメイン固有の Cookie が設定されます。ドメイン A がドメイン B の Cookie を読み取ろうとする試みは、Cookie アクセスの同一生成元ポリシーに違反します。

私はWCFを知らないので、あなたが望むことを実際にX-WCF-Auth行うための最良の方法はわかりませんが、解決策は、そのドメインのCookie(ヘッダーなど)を介さずに認証トークンを渡すことだと思いますA は独自の Cookie を読み取り、設定します。

于 2013-02-04T14:56:28.827 に答える
2

以下を設定していないため、ブラウザーのセキュリティ ポリシーによって応答がブロックされる可能性があります。

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials","true");

それでも解決しない場合は、追加してみてください

xhrFields: { withCredentials: true }

あなたajaxのオプションにも試してみる価値があるかもしれません。

于 2013-02-04T14:28:17.643 に答える