本地 AJAX-调用远程站点在 Safari 中有效,但在其他浏览器中无效

local AJAX-call to remote site works in Safari but not in other browsers

我正在维护一个使用 Javascript 的网站。该脚本使用 jQuery 并从正常托管站点的服务器加载一些内容。

为了在维护站点时方便,我 运行 在我的 iMac 上创建了站点的本地副本。当我使用 Safari 时,这工作得很好。但是 Firefox、Opera 和 Chrome 拒绝工作。我想这是因为跨域策略。 (我无法用 IE 对此进行测试,因为 IE 必须 运行 在我的 iMac 上的虚拟机中,因此无法访问任何本地文件)

Firefox 和其他浏览器中是否有设置,我可以告诉浏览器可以 ajax- 从本地 html- 加载位于远程服务器上的文件带有本地 javascript?

的页面

简而言之:这是我的 html 页:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>some title</title>
        <link rel="stylesheet" type="text/css" href="../css/stylesheet.css">
        <script src="../js/jquery-2.1.3.min.js"></script>
        <script src="../js/myScript.js"></script>
    </head>
    <body>
        <!-- some content with a div-container to receive the ajax-content -->
    </body>
</html>

这是myScript.js:

var errorMsg = function (msg) {
    //insert the message into the html-page
};

var JSONerror = function (jqXHR, textStatus, errorThrown ) {
    var msg = 'JSON-answer: '+jqXHR.responseText;
    msg += '<br>'+'JSON-Errorstatus: '+textStatus;
    if ($.type(errorThrown) === 'string') {
        msg += '<br>'+'Error: '+errorThrown;
    }
    errorMsg(msg);
};

var JSONreceive = function (JSONobj, StatusString, jqXHR) {
    //insert the data in JSONobj into the html-page
}

var StartAJAX = function () {
    $.ajax({
        url: 'http://my.domain.tld/cgi-bin/myPerlScript.pl',
        data: "lastID=" + lastID
           + '&qkz=' + Math.random(),
           dataType: "json",
           success: JSONreceive,
           error: JSONerror
    });
};

还有一个事件侦听器,它侦听页面滚动和调整大小并检查一些其他约束(例如:是否已经有一个 ajax 调用正在进行?)。此侦听器调用 StartAJAX.

当它在 Safari 中我的页面 (file:///User/...) 的本地副本上调用 StartAJAX 时,我将 Ajax-content 完美地插入到我的html-文档。在其他浏览器中,我将错误消息插入 html 页面。它是:

JSON-Answer: undefined
JSON-Errorstatus: error
Error:

为什么它在 Safari 中有效,但在 Firefox、Chrome 和 Opera 中无效?

如何让这些浏览器正常工作?

(我需要在所有浏览器上测试它,因为所有浏览器都以不同方式呈现相同的 html-文档,但我不想在每次更改后将所有文件上传到服务器只是为了测试它.)

编辑:

看完一些回答,我想说清楚一点,显然我没有说清楚:

我正在 Webbrowsers 中搜索设置

  1. 我不会更改远程网络服务器 (Apache) 的设置
  2. 我不会操作远程计算机 (.htaccess) 上的任何文件
  3. 我不会在本地 iMac 上设置网络服务器
  4. 我不会更改 Javascript-文件中 AJAX-调用的代码
  5. 我不会更改远程服务器上的 Perl 脚本代码

我可以告诉你原因:

我只是做一个简短的维护,我懒得在编辑后将每个操作的文件上传到远程机器。网络服务器的设置适合​​实际操作。我不想更改它们(并且可能在完成我的工作之前忘记更改)。脚本也是如此:你们中的一些人想要更改的那些部分现在可以正常工作。没有理由触及 Ajax-调用,因为它们在生产环境中没有任何问题。

我只想要那些愚蠢的浏览器 Firefox、Opera 和 Chrome 像 Safari 一样运行并正确处理 Ajax-调用。

顺便说一句:

谁能解释一下在 Firefox、Opera 或 Chrome 中通过 Ajax 从其他域调用数据有什么风险,而在 Safari 中做同样的事情似乎无害?

CHROME

有一个plugin for chrome that will force it to ignore the security policy. You can also do this with flags。请注意,请不要在启用此功能的情况下浏览 "real web",因为这会给您的计算机带来安全风险。

FIREFOX

This thread表示目前在firefox中没有办法做到这一点。

歌剧

同样,似乎没有内置的方法来忽略 CORS 策略。

另一种方法是让服务器 (http://my.domain.tld) 在您的情况下 return 正确的 headers - 特别是 Access-Control-Allow-Origin:

为避免此问题,您应该使用网络服务器(如 apache、nginx 等)开发您的页面(在您的本地计算机上没问题),因此,您的 url ajax调用以协议 http 或 https 开头,而不是 "file"。 "File" 是您的文件路径,但使用 SO 路径系统,而不是 Web 服务器系统。

另一方面,浏览器有 "Same Origin Policy"。这是一项安全功能,但使用 ajax 调用的 Web 开发中的 "problems" 是什么?好吧,您的 ajax 调用总是对同一台服务器进行,​​例如,如果您的网站位于域“http://my-domain.com" then your ajax calls must be to the same domain "http://my-domain.com”。

要"bypass" SOP in ajax调用,你有三种解决方案:

  • 在您的 "my-domain.com" 上创建一个使用 curl 的代理(例如在 php 中)来检索数据并 return 它到您的 ajax 通话
  • 使用JSON-P
  • 允许您的网络服务器中的域(例如 .htaccess)为 CORS 设置正确的配置:http://enable-cors.org/

顺便说一句

我要回答:“谁能解释一下通过 Ajax 从其他域 调用数据的风险有多大”。 (从 mozilla MDN https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy 复制粘贴)

The same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. Same-origin Policy is used as a means to prevent some of the Cross-site Request Forgery attacks.

由于同源策略,您通常无法从不同域请求资源。尝试将 crossDomain: true 添加到您的 AJAX 请求中,因为您正在尝试向其他域发出请求。

$.ajax({
    url: 'http://my.domain.tld/cgi-bin/myPerlScript.pl',
    crossDomain: true,
    data: "lastID=" + lastID
       + '&qkz=' + Math.random(),
       dataType: "json",
       success: JSONreceive,
       error: JSONerror
});

假设网站在域A,perl脚本在域B,你有两种选择: 1) 在域 B 的 Web 服务器上启用 CORS。http://enable-cors.org/ 2) 在域 A 上创建一个脚本(php、perl、ashx 等)来调用域 B 上的脚本。域 A 上的脚本将充当代理并且将被所有 Web 浏览器允许。