对远程站点的本地 AJAX 调用在 Safari 中有效,但在其他浏览器中无效
Posted
技术标签:
【中文标题】对远程站点的本地 AJAX 调用在 Safari 中有效,但在其他浏览器中无效【英文标题】:local AJAX-call to remote site works in Safari but not in other browsers 【发布时间】:2015-07-08 23:11:31 【问题描述】:我正在维护一个使用 javascript 的网站。该脚本使用 jQuery 并从通常托管该站点的服务器加载一些内容。
为了方便维护站点,我在 iMac 上运行站点的本地副本。当我使用 Safari 时,这工作得很好。但是 Firefox、Opera 和 Chrome 拒绝工作。我想这是因为跨域策略。 (我无法用 IE 进行测试,因为 IE 必须在我的 iMac 上的虚拟机中运行,因此无法访问任何本地文件)
在 Firefox 和其他浏览器中是否有一个设置,我可以告诉浏览器可以使用本地 javascript 从本地 html 页面 ajax 加载位于远程服务器上的文件?
简而言之:这是我的 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 内容完美地插入到我的 html 文档中。在其他浏览器中,我将错误消息插入到 html 页面中。它是:
JSON-答案:未定义 JSON-错误状态:错误 错误:
为什么它在 Safari 中有效,而在 Firefox、Chrome 和 Opera 中无效?
如何使这些浏览器正常工作?
(我需要在所有浏览器上测试它,因为所有浏览器都以不同的方式呈现相同的html-domument,但我不想在每次更改后将所有文件上传到服务器只是为了测试它。)
编辑:
看了一些答案,我想澄清一点,我显然没有说清楚:
我正在网络浏览器中搜索设置
-
我不会更改我的远程网络服务器 (Apache) 的设置
我不会操作远程计算机上的任何文件 (.htaccess)
我不会在本地 iMac 上设置网络服务器
我不会在我的 Javascript 文件中更改 AJAX 调用的代码
我不会更改远程服务器上 Perl 脚本的代码
我可以告诉你原因:
我只是做一个简短的维护,我懒得在编辑后将每个操作过的文件上传到远程机器。网络服务器的设置适合实际操作。我不想更改它们(并且可能在完成工作之前忘记更改)。脚本也是如此:你们中的一些人想要更改的那些部分现在可以正常工作。没有理由接触 Ajax-Calls,因为它们在生产环境中没有任何问题。
我只想让那些愚蠢的浏览器 Firefox、Opera 和 Chrome 表现得像 Safari 并正确处理 Ajax 调用。
顺便说一句:
请任何人解释一下在 Firefox、Opera 或 Chrome 中通过 Ajax 从其他域调用数据的风险如此之大,而在 Safari 中做同样的事情似乎是无害的?
【问题讨论】:
根据您的编辑,您不愿意接受任何答案,尽管它们是正确的。每个浏览器都有浏览器限制。如果您想让 Firefox、Chrome 和 Opera 像 Safari 一样运行,您需要联系这些浏览器的制造商并请求添加您需要的功能。此外,还提供了几个解决 CORS 问题的选项以及参考资料,以便您可以了解有关 AJAX 调用如何跨不同域工作的更多信息。这里没有任何人可以改变浏览器的设计方式。 @Rob:你的答案是目前最有可能赢得赏金的人。但赏金今天并没有结束。 3天结束,浏览量不到60次。这给了我 3 天的时间来希望另外 60 人阅读我的问题,并且其中一个人能找到更好的答案。如果在 3 天内没有答案告诉我如何操作浏览器以便它们根据需要执行 ajax 调用,那么我将接受您的回答。所以请耐心等待! 【参考方案1】:铬
有一个plugin for chrome 会强制它忽略安全策略。您也可以使用flags 执行此操作。请注意,请不要在启用此功能的情况下浏览“真实网络”,因为这会给您的计算机带来安全风险。
火狐
This thread 表示目前在 Firefox 中没有办法做到这一点。
歌剧
同样,似乎没有内置方法可以忽略 CORS 策略。
替代方法是让服务器 (http://my.domain.tld) 在您的情况下返回正确的标头 - 特别是 Access-Control-Allow-Origin:
【讨论】:
我不明白为什么这在 Chrome、Firefox 和 Opera 中存在安全风险,而在 Safari 中却没有?它在 Safari 中运行良好。 它在 safari 中工作的原因是因为 safari 忽略了 file: 方案的 CORS 策略,如果您要在本地服务器下运行并浏览到 localhost 以查看您的站点(并使您的请求my.domain.tld),它也会在 safari 中被阻止 - 请参阅 ***.com/a/27117909/430231 了解其他人对此主题所做的研究。 你可以用 --disable-web-security 标志启动 chrome【参考方案2】:为避免此问题,您应该使用网络服务器(如 apache、nginx、...)开发您的页面(在本地计算机上没问题),因此,您的 url ajax 调用以协议 http 或 https 开头,而不是“文件”。 “文件”是文件的路径,但使用的是 SO 路径系统,而不是 Web 服务器系统。
另一方面,浏览器具有“同源策略”。这是一项安全功能,但使用 ajax 调用进行 Web 开发的“问题”是什么?好吧,你的 ajax 调用总是在同一个服务器上完成,例如,如果你的网站在域“http://my-domain.com”上,那么你的 ajax 调用必须在同一个域“http://my-domain.com”上。
要在 ajax 调用中“绕过”SOP,您有三种解决方案:
在您的“my-domain.com”上创建一个代理,使用 curl(例如在 php 中)检索数据并将其返回给您的 ajax 调用 使用 JSON-P 允许您的域在您的网络服务器(例如 .htaccess)中为 CORS 设置正确的配置:http://enable-cors.org/顺便说一句
我将回答:“请任何人解释通过 Ajax 从其他域调用数据的风险如此之大”。 (从 Mozilla MDN https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy 复制粘贴)
同源策略限制如何从 一个来源可以与另一个来源的资源交互。 同源策略被用作防止某些 跨站点请求伪造攻击。
【讨论】:
我的 ajax 调用不以“file:///”开头,它们以“http://”开头。它是以“file:///”开头的网站。通常,我的 html 文档位于从浏览器接收 Ajax-Call 的同一远程服务器上。刚才,为了维护,我在本地机器上有一个 html 文件的操纵副本。 Ajax 调用仍会转到远程服务器,这在 Safari 中没有问题,但在所有其他浏览器中。 好的,所以,可能是一个 cors 问题,因为协议更改:“file”!==“http”。如果您的 web 服务调用转到远程服务器,那么您需要在服务器上添加 cors 支持。 我的问题是,我无法想象任何对任何人都有害的“跨站点请求伪造攻击”。如果你知道一些例子,请回答这个问题(我写的):***.com/questions/30108066/…【参考方案3】:由于相同的来源政策,您通常无法从不同的域请求资源。尝试将 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
);
【讨论】:
不,我不会更改在生产条件下完美运行的 Ajax 调用。我想更改浏览器中的一些设置,使其在本地计算机上维护文档期间接受来自远程服务器的数据。【参考方案4】:假设网站是域 A,而 perl 脚本位于域 B,您有两种选择: 1) 在域 B 的 Web 服务器上启用 CORS。http://enable-cors.org/ 2) 在域 A 上创建一个脚本(php、perl、ashx 等),调用域 B 上的脚本。域 A 上的脚本将充当代理,并且所有 Web 浏览器都允许。
【讨论】:
抱歉,您没有理解问题所在。一切都在同一个域上的正常条件下。所以没有理由改变服务器上的任何东西。当我因为维护而将 html 文档下载到本地 iMac 并将此本地文件加载到我的浏览器中时,才会出现问题。然后除 Safari 之外的所有浏览器都拒绝正确处理 Ajax 调用。在这种情况下,该网站不属于任何域。它是本地的。您的回答可能有助于解决其他一些问题,但不是我在问题中描述的问题。所以-1分。对不起。 你是对的。我确实假设当您说您正在运行网站的“本地”副本时,您确实是在“本地”Web 服务器上而不是从文件系统中运行它。那是对的吗?查看页面时,地址栏中显示的 url 是什么? 请仔细阅读我的问题。您要求的信息自 4 月底以来一直存在。 祝你好运。 由于浏览器安全..只允许处理不安全的网站以上是关于对远程站点的本地 AJAX 调用在 Safari 中有效,但在其他浏览器中无效的主要内容,如果未能解决你的问题,请参考以下文章
C# web页面 调用本地的mstsc.exe(远程桌面)?
跨域 Ajax 调用在 Safari 4 和 Safari 5 中不起作用
本地加载 XML 的 jQuery Ajax 问题 - Safari 版本 11.0 - 错误:XMLHttpRequest 无法加载 .xml。预检响应不成功