ajax跨域问题

来源:互联网 发布:视频剪辑用什么软件 编辑:程序博客网 时间:2024/04/26 10:36

之前面试的时候有个面试官问我ajax跨域的问题怎么解决,我完全不懂,答了一堆关于翻墙的问题,在学习ajax的时候,在写例子时遇到了本地域的问题和跨域的问题:

首先本地

代码如下:

    function loadXMLDoc(){    var xmlhttp;    if(window.XMLHttpRequest) {    xmlhttp = new XMLHttpRequest();    // ELSE CODE for IE6 IE5    } else {xmlhttp = new ActiveXObjext("Mixrosoft.XMLHTTP");}    // 当响应成功后执行的代码    xmlhttp.onreadystatechange=function() {    if(xmlhttp.readyState==4&&xmlhttp.status==200) {    document.getElementById("myDiv").innerHtml = "xmlhttp.responseText";    }    };    // 向服务器发送请求    xmlhttp.open("GET","./ajaxData.html",true);    // xmlhttp.open("GET","http://www.w3school.com.cn/ajax/demo_get.asp",true);    // 需要给服务器传递参数直接在url后面填写就可以了    xmlhttp.send();  }
报的错误是:XMLHttpRequest cannot load file:///D:/ajaxBegin/ajaxData.html. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.

跨域请求仅支持协议:HTTP,数据,Chrome,Chrome扩展,HTTPS,Chrome扩展资源。

造成原因是:

这是因为Chrome不支持本地的异步请求,因此直接通过file://访问文件就会报错!

解决办法:

        右击chrome快捷方式,选择“属性”,在“快捷方式”下的“目标”中添加" --allow-file-access-from-files"(最前面有个空格),重启chrome即可。

        

但是我这边用这个方法根本就更改不了chrome

然后我就想这不能本地的话那我就跨域:就用了下面注释的那行,还是报错:

XMLHttpRequest cannot load http://www.w3school.com.cn/ajax/demo_get.asp. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

意思是没有“访问控制允许源”标题是存在于所请求的资源上的。因此,“原点”是不允许访问。这就是跨域遇到了问题。

所以什么是跨域呢:

跨域是指从一个域名的网页去请求另一个域名的资源。比如从http://www.baidu.com/ 页面去请求 google.com 的资源。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域。 

以下内容转载至:http://www.w3cfuns.com/notes/17203/516a7995fc37af52832a6ea038ded262.html(这个 前端网站很好)

出现跨域时会提示:Uncaught SecurityError: Blocked a frame with origin "https://www.baidu.com" from accessing a frame with origin "http://127.0.0.1:8020".  The frame requesting access has a protocol of "https", the frame being accessed has a protocol of "http". Protocols must match.
总结起来就是:同一个域名,同一端口,同一协议,子域相同,同一二级域名;如果不同都是跨域

URL                                                            说明                                                    是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js                             同一域名下                                                        允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js                   同一域名下不同文件夹                                        允许
http://www.a.com:8000/a.js
http://www.a.com/b.js                            同一域名,不同端口                                           不允许
http://www.a.com/a.js
https://www.a.com/b.js                           同一域名,不同协议                                           不允许
http://www.a.com/a.js
http://70.32.92.74/b.js                           域名和域名对应ip                                                不允许
http://www.a.com/a.js
http://script.a.com/b.js                             主域相同,子域不同                                          不允许
http://www.a.com/a.js
http://a.com/b.js                                  同一域名,不同二级域名(同上)       不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js
http://www.a.com/b.js                                不同域名                                                           不允许



特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

简单地总结一下在“前台”一般处理跨域的办法,要解决跨域的问题,我们可以使用以下几种方法:
一、通过jsonp跨域(仅支持get请求)

                    <script type="text/javascript">
                       $.getJSON('http://example.com/data.php?callback=?,function(jsondata)'){
                           //处理获得的json数据
                         });
                    </script>
(jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。)

JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。

JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

二、CORS(跨域资源共享,Cross-Origin Resource Sharing)(支持所有类型的HTTP请求)

CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。
(服务器端这样处理)假设A页想要向B页面请求提取数据,则在B页中添加   Access-Control-Allow-Origin:A页面地址;,如果是允许任何域向我们的服务端提交请求:Access-Control-Allow-Origin:*;
( 前端这样处理)以前我们使用Ajax,代码类似于如下的方式:

var xhr = new XMLHttpRequest(); 
xhr.open("GET", "/hfahe", true); 
xhr.send(); 
这里的“/hfahe”是本域的相对路径。

如果我们要使用CORS,相关Ajax代码可能如下所示:

var xhr = new XMLHttpRequest(); 
xhr.open("GET", "http://blog.csdn.net/hfahe", true); 
xhr.send(); 
请注意,代码与之前的区别就在于相对路径换成了其他域的绝对路径,也就是你要跨域访问的接口地址

三、HTML5的window.postMessage方法(全称: 跨文档消息传输Cross Document Messaging)

window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

这个功能主要包括接受信息的”message”事件和发送消息的”postMessage”方法:

发送消息的”postMessage”方法:
otherWindow.postMessage(message, targetOrigin);
otherWindow:  指目标窗口,也就是给哪个window发消息,是 window.frames 属性的成员或者由 window.open 方法创建的窗口;
参数说明:
message:  是要发送的消息,类型为 String、Object (IE8、9 不支持);
targetOrigin:  是限定消息接收范围,不限制请使用 ‘*’;

接受信息的”message”事件:
var onmessage = function (event) {
    var data = event.data;
    var origin = event.origin;
    //需要做的事
};
if (typeof window.addEventListener != 'undefined') {
    window.addEventListener('message', onmessage, false);
} else if (typeof window.attachEvent != 'undefined') {
    //兼容IE
    window.attachEvent('onmessage', onmessage);
}

回调函数第一个参数接收 Event 对象,有三个常用属性:
data:  消息
origin:  消息来源地址
source:  源 DOMWindow 对象

四、当然解决方案也有很多:

document.domain+iframe的设置,应用于主域相同而子域不同;
利用iframe和location.hash,数据直接暴露在了url中,数据容量和类型都有限
Flash LocalConnection, 对象可在一个 SWF 文件中或多个 SWF 文件间进行通信, 只要在同一客户端就行,跨应用程序, 可以跨域。
window.name 保存数据以及跨域 iframe 静态代理动态传输方案,充分的运用了window.name因为页面的url改变而name不改变的特性。



1 0
原创粉丝点击