我正在维护一个使用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
。
当它在我的页面的本地副本上调用StartAJAX
时(file:///User/...)在Safari中,我可以将Ajax内容完美地插入到我的html文档中。在其他浏览器中,我将错误消息插入到html页面中。它是:
JSON应答:未定义
JSON错误状态:错误
错误:
为什么它能在Safari中工作,但不能在Firefox、Chrome和Opera中工作
如何使这些浏览器正常工作
(我需要在所有浏览器中测试它,因为所有浏览器都以不同的方式呈现相同的html文档,但我不想在每次更改后都将所有文件上传到服务器,只是为了测试它。)
编辑:
在阅读了一些答案后,我想说清楚一些我显然没有说清楚的东西:
我正在浏览器中搜索设置
- 我不会更改远程Web服务器(Apache)的设置
- 我不会操作远程计算机上的任何文件(.htaccess)
- 我不会在本地iMac上设置网络服务器
- 我不会更改Javascript文件中AJAX调用的代码
- 我不会更改远程服务器上Perl脚本的代码
我可以告诉你为什么:
我只是做了一个简短的维护,我太懒了,编辑完每个被操作的文件后都没有上传到远程机器上。Web服务器的设置对于实际操作来说很好。我不想改变它们(也许在完成工作之前忘记这些改变)。脚本也是如此:你们中的一些人想要更改的部分现在运行良好。没有理由接触Ajax调用,因为在生产环境中它们没有任何问题。
我只想让那些愚蠢的浏览器Firefox、Opera和Chrome表现得像Safari,并正确处理Ajax调用。
顺便说一句:
请有人解释一下,在Firefox、Opera或Chrome中通过Ajax从其他域调用数据有什么风险,而在Safari中做同样的事情似乎是无害的?
CHROME
chrome有一个插件会强制它忽略安全策略。您也可以使用标志执行此操作。注意,请不要在启用此功能的情况下浏览"真实网络",因为这会对您的计算机造成安全风险。
FIREFOX
这个线程表明目前在firefox中没有办法做到这一点。
OPERA
同样,似乎没有一种固有的方式来忽视CORS政策。
另一种选择是使用服务器(http://my.domain.tld)在您的情况下,返回正确的标头-特别是Access-Control-Allow-Origin:
为了避免这个问题,您应该使用Web服务器(如apache、nginx…)开发您的页面(在本地计算机中也可以),因此,您的url-ajax调用以协议http或https开始,而不是以"文件"开始。"文件"是文件的路径,但使用SO路径系统,而不是web服务器系统。
另一方面,浏览器有"同源策略"。这是一个安全特性,但使用ajax调用进行web开发时存在哪些"问题"?好吧,您的ajax调用总是对同一台服务器进行,例如,如果您的web在域上"http://my-domain.com"那么您的ajax调用必须在同一个域中"http://my-domain.com".
要在ajax调用中"绕过"SOP,您有三个解决方案:
- 在"mydomain.com"上创建一个代理,使用curl(例如php)检索数据并将其返回到ajax调用
- 使用JSON-P
- 允许您在Web服务器中的域(例如.htaccess)将正确的配置设置为CORS:http://enable-cors.org/
BTW
我将回答:">请任何人解释一下,通过Ajax从其他域调用数据有什么风险"。(从mozilla MDN复制并粘贴https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy)
同源策略限制如何从一个来源可以与另一个来源的资源交互。同源政策被用作防止跨站点请求伪造攻击。
由于同源策略,您通常无法从不同的域请求资源。尝试将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浏览器都允许使用。