跨域:当协议、主域名、子域名、端口号中任意一个不相同时都不算同一个域,而在不同域之间请求数据即为跨域请求。解决方法有以下几种(如有错误欢迎指出)以请求图片url为例:
1.通过XMLHttpRequest对象实现(IE10以下不支持)
XMLHttpRequest2.0已经实现了对CORS的原生支持,只需要在访问资源的时候使用绝对URL即可,需要在服务器端将头信息“Access-Control-Origin"设为”*“或当前域名的地址:
html&javascript:
1 2 3 4 5
这个例子是在本地测试的,html文件所在的位置是localhost:8085下,虽然127.0.0.1也是指的localhost,但他们也不是同一个域,可以利用这两个地址来模拟跨域请求。
php:
php header("Content-Type:text/plain"); header("Access-Control-Allow-Origin:http://localhost:8085");//设置头部,不设置的话请求会被拒绝 echo '{"src":"http://www.pinkbluecp.cn/face_alignment/img/picture.jpg"}'; ?>
post请求也差不多:
btn.onclick = function() { if(typeof XMLHttpRequest != 'undefined'){ var xhr = new XMLHttpRequest(); }else if(typeof ActiveXObject != 'undefined'){ var xhr = new ActiveXObject("Microsoft.XMLHTTP"); } xhr.onreadystatechange = function() { console.log(1) if(xhr.readyState == 4 && xhr.status == 200){ console.log(2) pic.innerHTML = xhr.responseText; } } xhr.open('POST','http://127.0.0.1:8085/AJAX/ajax/server.php',true); xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); //需要设置下头部 var str = 'active=login'; xhr.send(str);
php
php header("Content-Type:text/plain"); header("Access-Control-Allow-Origin:http://localhost:8085"); if($_POST['active'] == 'login'){ echo 'success'; }else { echo "error"; } ?>
发送数据需要设置一下头部的Content-Type字段。
2.IE(8-10)中实现CORS:
IE8中引入了XDomainRequest对象,该对象和XHR相似,但它能实现安全可靠的跨域通信,不过在IE11中已经无法使用了。
1 var btn = document.getElementById('btn'), 2 pro = document.getElementById('process'), 3 pic = document.getElementById('img'); 4 5 btn.onclick = function() { 6 var xhr = new XDomainRequest(); 7 xhr.onload = function() { 8 var img = document.createElement('img'); 9 console.log(xhr.responseText) 10 // img.src = JSON.parse(xhr.responseText).src; 11 img.src = xhr.responseText; 12 console.log(img.src); 13 pic.appendChild(img); 14 }; 15 xhr.onerror = function() { //XDR无法确定响应状态,需要添加onerror来检测错误 16 alert("Error!"); 17 } 18 xhr.open('GET','http://127.0.0.1:8085/AJAX/ajax/server.php'); //该对象的的请求都是异步,没有第三个参数 19 xhr.send(null); 20 }
XDR与XHR不同之处在于:
a. cookie不会随请求发送,也不会随响应返回
b. 只能设置请求头中的Content-Type字段
c. 不能访问响应头部信息
d. 只支持GET和POST请求
两者的方法也略有不同,XDR的open方法只有异步一种状态,所以只要传两个参数method和url,在请求返回之后会触发load事件,但无法获取响应状态码,所以想判断请求是否成功只能添加error事件。它也可以和XHR一样添加超时。
关于XDR的post请求,虽然js高编上有介绍,但是在多次尝试后发现已经行不通了,高编上说XDR有专门的属性contentType来设置请求头信息,但在浏览其中会报错:
无法进行设置contentType的操做,后来查阅了一下这篇博客,貌似XDR已经无法在设置请求头了,详情可以去看原博。
3. 实现跨浏览器的CORS
js高编上有一段实现跨浏览器的CORS实现函数:
除了IE10-外所有浏览器都有withCredentials属性,所以可以根据这个属性来判断是否支持XMLHttpRequest2.0.
4.图片Ping
图片Ping就是利用图片的src可以使用跨域资源的特性来实现,但是只能实现简单的单向请求,在img的src中传入一个其他域的url并附带一些参数。
5.JSONP
JSONP和图片Ping很相似,也是利用script标签中的链接不受同源限制可以向不同域传递信息,但它传递的是一个已经存在的回调函数,服务器接收到后,将响应数据传入该回调函数并执行该函数从而达到获取数据的目的。
先来看下