xmlHttp.getResponseHeader +不适用于CORS
我在.NET 4上有一个asp.net WCF。这个服务用来authentication用户。 我们正在提交一个用户名和密码,然后应该返回一个HTTP头,包括authenticationcookie。 使用本地托pipe的testing页面,这是正常工作。 我现在正试图访问标题信息跨域。 我已经在另一台机器上安装了我的testing页面,并将其configuration为与WCF进行通话。 通话正在进行,通话中的“数据”回复是正确的。 但是,我无法使用以下任一项访问标题信息:
alert(xmlHttp.getAllResponseHeaders());
要么
alert(xmlHttp.getResponseHeader("Set-Cookie"));
使用IE中的debugging器和Firefox的“Live HTTP Header”插件,我可以看到正在返回的头信息。
在我的全球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 } }); } });
以下是我从“Live 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
首先,有一点背景:
您正在使用Access-Control-Allow-Headers
,它指定允许客户端发送哪些请求头,但是您没有指定允许客户端读取哪个响应头。 要允许客户端读取非简单的响应头,您需要使用Access-Control-Expose-Headers
。 从HTML5 Rocks CORS页面 :
在CORS请求期间,
getResponseHeader()
方法只能访问简单的响应头。 简单的响应标题定义如下:
- caching控制
- 内容语言
- 内容types
- 过期
- 上一次更改
- 附注
如果您希望客户端能够访问其他标题,则必须使用
Access-Control-Expose-Headers
标题。 这个头文件的值是一个逗号分隔的你想要公开给客户端的响应头列表。
所以,给出这个新的信息,你可能会这样做:
HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "Set-Cookie");
…但除此之外还有更多。
现在,实际的答案是:
这里还有一个更严重的问题:XHR规范明确地禁止读取Set-Cookie
。 这是因为这在function上是一个跨域的cookie窃取攻击 。
假设域A向域B发出跨域请求。当域B设置cookie时,它仅为域B设置域特定的cookie。 域A读取域B的cookie的任何企图都违反了cookie访问的同源策略。
我不知道WCF,所以我不是最好的方式来实际做你想做的事情,但我想这个解决scheme可能是通过一个身份validation令牌不通过cookie(例如,一个X-WCF-Auth
头?)域A读取,然后设置自己的cookie。
浏览器的安全政策可能会阻止您的回应,因为您尚未设置:
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials","true");
如果这没有帮助,请尝试添加
xhrFields: { withCredentials: true }
到你的ajax
选项也可能值得一试。