xmlHttp.getResponseHeader + 不适用于 CORS [英] xmlHttp.getResponseHeader + Not working for CORS

查看:30
本文介绍了xmlHttp.getResponseHeader + 不适用于 CORS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 .NET 4 上有一个 asp.NET WCF.此服务用于对用户进行身份验证.我们正在提交用户名和密码,然后应返回包含身份验证 cookie 的 HTTP 标头.使用本地托管的测试页面可以正常工作.我现在正在尝试跨域访问标头信息.我已经在另一台机器上安装了我的测试页面,并配置为调用 WCF.通话正常,通话中的数据"回复正确.但是,我无法使用以下任一方式访问标头信息:

I have an asp.NET WCF on .NET 4. This service is used to authenticate users. We are submitting a username and password and then an HTTP Header should be returned with the authentication cookie included. Using a locally hosted test page this is working correctly. I am now attempting to access the header information cross domain. I have installed my test page on a different machine and configured to call across to the WCF. The call is working and the 'data' reply in the call is correct. However, I am unable to access the header information with either of the following:

alert(xmlHttp.getAllResponseHeaders());

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

使用 IE 中的调试器和 Firefox 的Live HTTP 标头"插件,我可以看到正在返回标头信息.

Using the debugger in IE and the 'Live HTTP Header' plugin for Firefox, I can see the header information is being returned.

在我的全局 ajax 页面中,我正在设置响应以处理 CORS.

In my global ajax page I am setting the response to handle 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:

This is the AJAX I am using to call the service:

$("#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("
");
            var output = '';
            $.each(headerPair, function(key, line) {
                var parts = line.split(':');

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

            });
        }
    });

以下是我从实时 HTTP 标头"中抓取的标头信息

Below is my header information grabbed from 'Live HTTP headers'

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

推荐答案

首先介绍一下背景:

您正在使用 Access-Control-Allow-Headers,它指定允许客户端发送哪些请求标头,但是您未指定允许客户端读取响应标头.要允许客户端读取非简单响应头,您需要使用 Access-Control-Expose-Headers.来自 HTML5 Rocks CORS 页面:

You are using Access-Control-Allow-Headers, which specifies which request headers the client is allowed to send, but you are not specifying which response headers the client is allowed to read. To allow the client to read non-simple response headers, you need to use Access-Control-Expose-Headers. From the HTML5 Rocks CORS page:

在 CORS 请求期间,getResponseHeader() 方法只能访问简单的响应头.简单的响应头定义如下:

During a CORS request, the getResponseHeader() method can only access simple response headers. Simple response headers are defined as follows:

  • 缓存控制
  • 内容语言
  • 内容类型
  • 过期
  • 上次修改
  • 语用

如果您希望客户端能够访问其他标头,则必须使用 Access-Control-Expose-Headers 标头.此标头的值是以逗号分隔的要向客户端公开的响应标头列表.

If you want clients to be able to access other headers, you have to use the Access-Control-Expose-Headers header. The value of this header is a comma-delimited list of response headers you want to expose to the client.

因此,鉴于这些新信息,您可能会这样做:

So, given that new information, you might do:

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

...但还有更多.

现在,实际答案:

这里还有一个更严重的问题:XHR 规范明确地不允许读取 Set-Cookie.这是因为这在功能上是一种跨域 cookie 窃取攻击.

There's one more serious problem here: the XHR specification explictily disallows reading Set-Cookie. That's because this is functionally a cross-domain cookie-stealing attack.

假设域 A 向域 B 发出跨域请求.当域 B 设置 cookie 时,它​​正在为域 B 设置特定于域的 cookie.域 A 试图读取域 B 的 cookie 的任何尝试都违反了 cookie 访问的同源策略.

Suppose domain A makes a cross-domain request to domain B. When domain B sets cookies, it's setting domain-specific cookies for domain B only. Any attempt by domain A to read domain B's cookies is a violation of the same-origin policy for cookie access.

我不知道 WCF,所以我不确定实际上做你想做的最好的方法,但我猜解决方案可能是传递一个不通过的身份验证令牌域 A 读取的 cookie(例如,X-WCF-Auth 标头?)然后设置自己的 cookie.

I don't know WCF, so I'm not the sure of best way to actually do what you want, but I'd guess the solution might be to pass an auth token not through cookies (e.g., a X-WCF-Auth header?) that domain A reads and then sets its own cookie.

这篇关于xmlHttp.getResponseHeader + 不适用于 CORS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆