6

这让我发疯。

jQuery 1.4.2,Windows XP sp3

这是我的测试。

加载火狐3.5+

http://plungjan.name/test/testcors.html

作品

将文件保存到硬盘并从那里运行

在我的办公室里,外部工作,内部不工作

有趣的是,我不能同时跑两个。

背景:我对使用CORS的内部 Web 服务执行GET操作。请不要发布任何关于 FF 自 v3.5 以来不处理跨域请求的答案,详见此处此处

它在 IE8 和 FF3.6.6 中从一台服务器到另一台服务器,现在几乎从文件系统 (file:///) 到服务。 只有来自文件系统并且只有当 FF 3.6.6 需要协商(用户已经登录、授权并发送凭据!)时,我才不会在协商后获取数据。jQuery xhr 返回状态 0 并且没有数据/响应文本或任何在我看来,jQuery 做出反应并从 401 中保存 xhr,而不是稍后从 200 OK

以下是我在提醒 XHR 对象时在通信结束时得到的结果:

Status:success 
Data:[] 
XHR: 
some native functions,
readyState:4 
status:0
responseXML:null 
responseText: 
withCredentials:true

如果我调用同一台服务器但不需要凭据,则跨域返回数据就好了

于是通讯如下:

GET /restapplicationusingcors/authenticationneeded-internal/someid
Accept: application/json
Accept-Language: en
.
.
Origin: null
Cookie: LtpaToken=...

回报是

HTTP/1.1 401 Unauthorized
Server: Apache
Pragma: No-cache
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 01:00:00 CET
WWW-Authenticate: Negotiate
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html

然后FF发送

GET /restapplicationusingcors/authenticationneeded-internal/someid HTTP/1.1
Host: myhost.myintranet.bla
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6
Accept: application/json
Accept-Language: en
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: null
Cookie: LtpaToken=....
Authorization: Negotiate ....

并获得我需要的文件,但无法在 FF 中获取:

HTTP/1.1 200 OK
Date: Tue, 20 Jul 2010 12:08:39 GMT
Pragma: No-cache
Cache-Control: no-cache, max-age=600, s-maxage=3600
Expires: Thu, 01 Jan 1970 01:00:00 CET
X-Powered-By: ...
Content-Disposition: inline;filename=nnnnnn.json
Content-Language: en
Access-Control-Allow-Origin: ...
Keep-Alive: timeout=6, max=70
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json;charset=UTF-8

从服务器发送的数据不在XHR对象中

这是我的代码

function getJSON(url,func,lang) {
  accept = 'application/json';
  lang=lang?lang:"*";
  // gruesome hack to handle that APPENDS the mime header to */* !!!
  // NOW HANDLED by first setting Accept to "" !!! 
//  if ($.browser.msie && url.indexOf('serveAsMime')==-1)  {
//    url+= '?serveAsMime='+accept;
//  }
  if (currentRequest != null) currentRequest.abort();
  var requestObjectJSON =   {
    url    : url,
//    dataType: "json",
    method : 'get',
    beforeSend: function(xhr){
      xhr.setRequestHeader('Accept', ""); // IE hack
      xhr.setRequestHeader('Accept', accept);
      xhr.setRequestHeader('Accept-Language', lang);
      if (url.indexOf('-internal') !=-1) {
        try {
          xhr.withCredentials = true;
          alert('set credentials') 
        }
        catch(e) {
          alert('cannot set xhr with credentials')
        }
      }
    },

    success: function(data,status,xhr) {
      var responseText = xhr.responseText;
      var responseJSON = xhr.responseJSON;


      var t = "";
      try{
        for (var o in xhr) t += '\n'+o+':'+xhr[o];
      }
      catch(e) {
        if (e.message.indexOf('.channel')==-1)alert(e.message);
      }
      alert('Status:'+status+'\nData:['+data+']\nXHR:'+t);
      func(responseText);
    },
  }
  currentRequest = $.ajax(requestObjectJSON);
}
4

4 回答 4

3

这是一个黑暗中的刺,因为我不完全理解你的问题,但我认为你可能对file:不被视为具有任何来源的 URL 有问题。我不确定是否可以从文件 URL 授权 CORS。

于 2010-07-31T02:01:59.597 回答
1

因此,您需要在模型/集合中设置一个 ajax 预过滤器才能使用 CORS。否则它不会发送 cookie。

$.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
    options.xhrFields = {
      withCredentials: true
    };
});

我把它放在我的模型/集合初始化函数中。

于 2012-06-07T20:37:15.927 回答
1

这些是使 CORS 与安全服务一起工作需要满足的条件:

  • 服务响应应包含标头Access-Control-Allow-Credentials: true(请参阅带有凭据的请求和凭据标志为 true 时无法在 Access-Control-Allow-Origin 中使用通配符)。
  • 服务响应标头Access-Control-Allow-Origin不应该是*. 这个想法是返回客户端在标头中传递的值Origin(参见本文中的示例)。
  • 根据规范,OPTIONS方法应该返回 HTTP 代码 200,因此它不能被保护(参见CORS)。
  • 对于需要将某些请求标头传递给服务的方法PUT/ (如或),这些标头需要在中列出(请参阅指定标头时 jQuery AJAX 无法工作POSTContent-TypeAcceptAccess-Control-Allow-Headers
  • JavaScript 应该设置这个XMLHttpRequest属性:(由Kirbyxhr.withCredentials = true;回答)

Apache的总配置:

# Static content:
SetEnvIf      Request_URI     ".*"                            no-jk
# RESTful service:
SetEnvIf      Request_URI     "^/backend/"                    !no-jk
SetEnvIf      Request_Method  "OPTIONS"                       no-jk
# Fallback value:
SetEnv        http_origin     "*"
SetEnvIf      Origin          "^https?://(localhost|.*\.myconpany\.org)(:[0-9]+)?$" http_origin=$0

Header        set Access-Control-Allow-Credentials    "true"
Header        set Access-Control-Allow-Origin         "%{http_origin}e"
Header        set Access-Control-Allow-Methods        "GET,POST,PUT,DELETE"
Header        set Access-Control-Allow-Headers        "Content-Type, Accept"

JkMount /* loadbalancer
于 2014-05-27T12:45:03.493 回答
0

CORS 与file://

如果您在允许来自file://协议的来源时遇到问题,根据The Web Origin Concept,它应该以与任何其他来源相同的方式完成。我找不到有关浏览器支持的信息,但我认为每个支持 CORS 的浏览器都支持这个。

Web Origin Concept 告诉我们有关文件 URI 方案的以下内容:

   4.  If uri-scheme is "file", the implementation MAY return an
       implementation-defined value.

          NOTE: Historically, user agents have granted content from the
          file scheme a tremendous amount of privilege.  However,
          granting all local files such wide privileges can lead to
          privilege escalation attacks.  Some user agents have had
          success granting local files directory-based privileges, but
          this approach has not been widely adopted.  Other user agents
          use globally unique identifiers for each file URI, which is
          the most secure option.

根据维基百科,文件 URI 方案的域是 localhost。地址栏可以省略它,但我不认为它在允许来源标头中可以省略。因此,如果您的浏览器实现允许使用文件 URI 方案的来源,那么您应该添加file://localhost到允许的来源,之后一切都应该正常工作。

这是它应该如何工作,现在满足现实:

  • 我用当前的 Firefox 29.0.1 进行了测试,但它不起作用。但是,该file://协议通过此实现转换为null原始协议。所以通过firefox的null作​​品。我尝试使用更广泛的域列表,但我没有设法允许多个域。似乎firefox目前不支持具有多个域的列表。
  • 我用 chrome 35.0.1916 进行了测试,它的工作方式与 Firefox 相同。
  • 我用 msie 11.0.9600 进行了测试。通过文件协议的请求,它总是显示一个allow blocked content按钮,即使不允许空源。通过其他域,它的工作方式与以前的浏览器相同。

HTTP基本认证:

我尝试使用 PHP 和 HTTP 基本身份验证的凭据部分。

http://test.loc
登录时显示:-),未授权时显示:-(。

<?php

function authorized()
{
    if (empty($_SERVER['PHP_AUTH_USER']) || empty($_SERVER['PHP_AUTH_PW']))
        return false;
    return ($_SERVER['PHP_AUTH_USER'] == 'username' && $_SERVER['PHP_AUTH_PW'] == 'password');
}

function unauthorized()
{
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Basic realm="Restricted Area"');
    echo '<a href="http://test.loc">:-(</a>';
}

if (!isset($_GET['logout']) && authorized()) {
    echo '<a href="http://test.loc?logout=1">:-)</a>';
} else
    unauthorized();

因此,此代码通过登录和注销来更改位置。

具有 HTTP 基本身份验证的跨域 CORS

http: //todo.loc通过跨域
XHR获取 http://test.loc 的内容并显示出来。

cross domain ajax<br />
<script>
    var xhr = new XMLHttpRequest();
    xhr.open('GET', "http://test.loc", true);
    xhr.withCredentials = true;
    xhr.onreadystatechange = function (){
        if (xhr.readyState==4) {
            document.body.innerHTML += xhr.responseText;
        }
    };
    xhr.send();
</script>

需要http://test.loc的标头:

Access-Control-Allow-Origin: http://todo.loc
Access-Control-Allow-Credentials: true

具有 HTTP 基本身份验证的跨方案 CORS

file:///path/x.html使用交叉方案XHR 获取http://test.loc
的内容并显示。

cross scheme ajax<br />
<script>
    var xhr = new XMLHttpRequest();
    xhr.open('GET', "http://test.loc", true);
    xhr.withCredentials = true;
    xhr.onreadystatechange = function (){
        if (xhr.readyState==4) {
            document.body.innerHTML += xhr.responseText;
        }
    };
    xhr.send();
</script>

需要http://test.loc的标头:

Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true

结论:

我使用 from 调用的凭据测试了跨 sheme CORS,file://它在 firefox、chrome 和 msie 中运行良好。

于 2014-05-27T14:06:19.173 回答