【问题标题】:Please help test a CORS issue in Firefox jQuery ajax when 401请在 401 时帮助测试 Firefox jQuery ajax 中的 CORS 问题
【发布时间】:2011-03-18 10:22:35
【问题描述】:

这让我发疯了。

jQuery 1.4.2,Windows XP sp3

这是我的测试。

加载firefox 3.5+

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

作品

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

在我的办公室里,外部有效,内部无效

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

背景: 我对使用CORS 的内部Web 服务执行GET。 请不发布任何关于 FF 自 v3.5 以来未处理跨域请求的答案,详细信息 here 和 here

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

这是我在通信结束时提醒 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);
}

【问题讨论】:

  • “将文件保存到硬盘并从那里运行。在我的办公室里,外部工作正常,内部工作不工作。”我不明白。外部/内部什么有效?
  • 重新标记。如果你使用更流行的标签,你会得到一些答案.. ;)
  • ...和一个更具描述性的问题标题。
  • 您是否检查过任何公司防火墙和/或安全软件?我遇到了 jQuery/Ajax 问题,公司安全措施正在检测 Ajax 请求并阻止它们——我最终遇到了与您所得到的类似的错误。这可能是一个远景,因为情况有些不同,但这是一个想法。
  • 标题比一个星期更具描述性!标签具有代表性。 Nathan:防火墙完全没有问题,因为原始代码在防火墙内运行。

标签: javascript json authentication jquery cors


【解决方案1】:

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

【讨论】:

  • 这是真正的问题。但没有回答。
  • 我这里有一个测试,现在通过身份验证根本不起作用:( talent-aid.org/test/testcors.html
  • 我试过那个测试,老实说我不知道​​它是否失败,以及在什么情况下失败。我也不明白这是否是 file: 的问题,401 响应的问题,一般的身份验证问题,还是什么。你真的解释得不好。
  • 对不起,我直到现在才看到这篇文章。我只能在 Intranet 上真正展示这一点。症状是它在 IE8 中完美运行,而 FF 仅在 html 位于文件系统上并且仅当其余调用需要身份验证时才会失败,例如当服务器 FIRST 返回 401 并且当它从浏览器获得身份验证并发送数据时,FF 或 jQuery 不会将数据传递给脚本,但仍会给出 OK 返回码......我希望人们看到标头和 XHR 返回代码已经将此识别为 FF 或 jQuery 中的错误,并且知道解决方法。谢谢
  • 这听起来像是 Firefox 中的一个错误(或者可能是 jQuery,但我对此表示怀疑)。尝试在这里再次提出这个问题:support.mozilla.com/en-US/questions/new
【解决方案2】:

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

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

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

【讨论】:

  • 谢谢 - 一年后的现在有点没有实际意义。我感谢您的努力,并希望它对其他人有所帮助。我不需要代码也不需要服务器来测试它
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    带有file://的CORS

    如果您在允许来自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.
    

    根据wikipedia文件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
    用cross scheme XHR 获取http://test.loc 的内容并显示出来。 em>

    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
    

    结论:

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

    【讨论】:

    • 来自文件协议的来源为空白。不再重要 这是 FX 3.5 中的一个非常古老的问题 - 我们现在拥有 FX27 并改变了我们使用它的方式。不过谢谢
    • 是的,我刚刚发现现在每个浏览器都使用null origin。
    猜你喜欢
    • 2014-11-11
    • 2015-08-20
    • 1970-01-01
    • 2015-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    相关资源
    最近更新 更多