JSONP、图片Ping、XMLHttpRequest2.0等跨域资源请求(CORS)
跨域:当协议、主域名、子域名、端口号中任意一个不相同时都不算同一个域,而在不同域之间请求数据即为跨域请求。解决方法有以下几种(如有错误欢迎指出)以请求图片url为例:
1.通过XMLHttpRequest对象实现(IE10以下不支持)
XMLHttpRequest2.0已经实现了对CORS的原生支持,只需要在访问资源的时候使用绝对URL即可,需要在服务器端将头信息“Access-Control-Origin"设为”*“或当前域名的地址:
html&javascript:
<button id="btn">load</button>
<div id="process"></div>
<div id="img"></div> <script>
var btn = document.getElementById('btn'),
pro = document.getElementById('process'),
pic = document.getElementById('img'); btn.onclick = function() { var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() { if(xhr.readyState == 4 && xhr.status == 200){
var img = document.createElement('img');
img.src = JSON.parse(xhr.responseText).src;
pic.appendChild(img);
}
}
xhr.open('GET','http://127.0.0.1:8085/AJAX/ajax/server.php',true);
xhr.send(null);
}
</script>
这个例子是在本地测试的,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中已经无法使用了。
 var btn = document.getElementById('btn'),
             pro = document.getElementById('process'),
             pic = document.getElementById('img');
         btn.onclick = function() {
             var xhr = new XDomainRequest();
             xhr.onload = function() {
                 var img = document.createElement('img');
                 console.log(xhr.responseText)
                 // img.src = JSON.parse(xhr.responseText).src;
                 img.src = xhr.responseText;
                 console.log(img.src);
                 pic.appendChild(img);
             };
             xhr.onerror = function() {  //XDR无法确定响应状态,需要添加onerror来检测错误
                 alert("Error!");
             }
             xhr.open('GET','http://127.0.0.1:8085/AJAX/ajax/server.php'); //该对象的的请求都是异步,没有第三个参数
             xhr.send(null);
         }        
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实现函数:
<button id="btn">load</button>
<div id="process"></div>
<div id="img"></div> <script>
var btn = document.getElementById('btn'),
pic = document.getElementById('img'); btn.onclick = function() {
console.log(1);
var xhr = createCORS('GET','http://127.0.0.1:8085/AJAX/ajax/server.php');
if(xhr){
console.log(2)
xhr.onload = function(){
console.log(3)
var img = document.createElement('img');
img.src = xhr.responseText;
pic.appendChild(img);
};
xhr.onerror = function() {
alert("Error");
};
xhr.send(null);
}
} function createCORS(method,url){ //参考js高编
console.log('fun')
var xhr = new XMLHttpRequest();
if('withCredentials' in xhr){ //检测是否含有凭据属性
xhr.open(method,url,true);
}else if(typeof XDomainRequest != 'undefined'){ //兼容ie
xhr = new XDomainRequest();
xhr.open(method,url);
}else {
xhr = null;
}
return xhr;
}
</script>
除了IE10-外所有浏览器都有withCredentials属性,所以可以根据这个属性来判断是否支持XMLHttpRequest2.0.
4.图片Ping
图片Ping就是利用图片的src可以使用跨域资源的特性来实现,但是只能实现简单的单向请求,在img的src中传入一个其他域的url并附带一些参数。
5.JSONP
JSONP和图片Ping很相似,也是利用script标签中的链接不受同源限制可以向不同域传递信息,但它传递的是一个已经存在的回调函数,服务器接收到后,将响应数据传入该回调函数并执行该函数从而达到获取数据的目的。
先来看下<script>标签中传入src得到的是什么:
<script src="test.txt"></script>
在src中传入一个文本文件

浏览器中报语法错误,hello world这个变量未定义,服务器响应的数据就时test.txt的内容,而script把这段纯文本当作js代码来解析,当在test.txt中将这段文字加上单引号后:

浏览器不报错了,因为把它当作字符串来解析了。现在把链接换成一个php文件:
php
<?php
echo "Hello World!";
?>

结果一样,浏览器同样也会报错,加上引号后同样也不报错,如果这时服务器端返回的是一个函数名,而该页面正好又有一个同名函数会怎样:
php:
<?php
echo "callback('hello world')";
?>
html
<body>
<script>
function callback(res){
alert(res);
}
</script>
<script src="jsonp.php"></script>
</body>
结果:

callback函数被执行了,因为后台的响应数据被script标签当作js代码执行了,所以这就能理解jsonp的原理了,利用这个回调函数可以获得后台传来的数据:
html:
<body>
<script>
function jsonp(res){
for(var i in res){
console.log("key:"+i+";value:"+res[i]);
}
}
</script>
<script src="jsonp.php?callback=jsonp"></script> //可动态创建
</body>
php:
<?php
$str = '{"name":"Lee","age":20}';
$callback = $_GET['callback'];
echo $callback."($str)";
?>
上面一个简单的例子展示了jsonp如何用回调函数获取服务器响应的json数据:


JSONP的有点在于可以访问到服务器的响应文本,不过缺点就是要从其他域加载代码执行,必须要保证其他域的安全性,不然可能响应信息中会附带恶意脚本,还有一点就是无法确定请求是否失败,即使失败也不会有提示。
6.iframe跨域
iframe跨域与jsonp相似,也利用了src不受同源限制的特性。当A域下的x.html页面要访问B域下的y.html中的信息可以通过A域下的z.html页面作为代理来获取信息:
x.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
</head> <body>
<iframe src="http://127.0.0.1:8085/AJAX/ajax/proxya.html" style="display: none"></iframe>
<p id="getText"></p>
<script>
function callback(text){
text = JSON.parse(decodeURI(text));
document.getElementById("getText").innerHTML= '姓名:' + text.name + '; 年龄:' + text.age;
}
</script>
</body>
</html>
y.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
</head> <body>
<iframe id="myfarme" src="###"></iframe>
<script>
window.onload = function(){
var text = '{"name":"cheng","age":22}'; //存储一个json格式的数据
document.getElementById('myfarme').src="http://localhost:8085/AJAX/ajax/proxyb.html?content="+encodeURI(text); //将数据传个代理页面处理,此时src中的地址不受同源限制,与jsonp相似
}
</script>
</body>
</html>
z.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script>
window.onload = function(){
var text = window.location.href.split('=')[1]; //通过分解url获取y.html传来的参数
top.callback(text); //调用x.html的callback函数
}
</script>
</head> <body>
</body>
</html>
JSONP、图片Ping、XMLHttpRequest2.0等跨域资源请求(CORS)的更多相关文章
- 004. 前端跨域资源请求: JSONP/CORS/反向代理
		
1.什么是跨域资源请求? https://www.cnblogs.com/niuli1987/p/10252214.html 同源: 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有 ...
 - JavaScript跨域资源请求(CORS)解决方案
		
跨域:当协议.主域名.子域名.端口号中任意一个不相同时都不算同一个域,而在不同域之间请求数据即为跨域请求.解决方法有以下几种(如有错误欢迎指出)以请求图片url为例: 1.通过XMLHttpReque ...
 - jsonp突破同源策略,实现跨域访问请求
		
跨域访问问题,相信大家都有遇到过.这是一个很棘手的问题.不过道高一尺,魔高一丈,对于这类问题,总有解决问题的方案.最近我又接触到了这个问题,解决的途径是ajax+jsonp. 说到这个问题,不得不说一 ...
 - 跨域资源请求(除jsonp以外)的方法
		
---------------------------------------------------------------------------------------------------- ...
 - .net MVC下跨域Ajax请求(CORS)
		
二.CROS (Cross-origin Resource Sharing) CROS相当于一种协议,由浏览器.服务端共同完成安全验证,进行安全的跨域资源共享.对于开发人员来说就跟在本站AJAX请求一 ...
 - jsonp实现跨域资源访问
		
平时项目中处理ajax跨域资源请求时,例如www.example2.com上的某个页面要请求www.example1.com的数据,我们使用得较多的是jsonp方式.jsonp通过JavaScript ...
 - 跨域资源共享(CORS)在ASP.NET Web API中是如何实现的?
		
在<通过扩展让ASP.NET Web API支持W3C的CORS规范>中,我们通过自定义的HttpMessageHandler自行为ASP.NET Web API实现了针对CORS的支持, ...
 - JSON和JSONP有哪些区别,PhoneGap跨域请求如何实现
		
前言 由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现. 当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Socke ...
 - asp.net web api2.0 ajax跨域解决方案
		
asp.net web api2.0 ajax跨域解决方案 Web Api的优缺点就不说了,直接说怎么跨域,我搜了一下,主要是有两种. 一,ASP.NET Web API支持JSONP,分两种 1, ...
 
随机推荐
- 整个IT界可分为13块大领域
			
IT界可以划分为13个领域 Location: NanJing
 - js正则知识点
			
正则主要是用来匹配有规律的字符串,也就是说你要写一个正则前你必须非常清楚该类型字符串的规则,(比如邮箱)如果你没了解邮箱的规则那么你正则无论怎么写都是错的. \w字符(字母数字下划线)\W非字符\s空 ...
 - JS学习一
			
js中的变量输出 [使用JS的三种方式] 1. 在HTML标签中,直接内嵌JS(并不提倡使用): <button onclick="alert('你真点啊!')"> ...
 - 五个数据段之代码段、数据段、BSS、栈、堆
			
继上文讲完了对内存管理的一些知识,下面笔者再对上篇文章的内容加以拓展,那么我们今天就来说一说5个数据段 五个数据段 进程(执行的程序)会占用一定数量的内存,它或是用来存放磁盘载入的程序代码,或是存放取 ...
 - 团队作业4——第一次项目冲刺(Alpha版本) 日志集合处
			
第一天(2017.4.23) http://www.cnblogs.com/1413none/p/6752325.html 第二天(2017.4.24) http://www.cnblogs.com/ ...
 - 201521123025<java程序设计>第五周学习总结
			
1. 本周学习总结 2. 书面作业 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 1.2 ...
 - 学号:201521123116  《java程序设计》第一周学习总结
			
#1. 本章学习总结了解了班级的纪律和期末成绩组成.本周重点学习了java语言的特点具有简单性和结构中立.明白了jdk是java开发人员使用的一种工具,以及编写一个java程序的所需步骤,懂得了jdk ...
 - Python中库或者模组的解释
 - Python[小甲鱼007了不起的分支和循环]
			
加载背景音乐播放背景音乐(设置单曲循环)我方飞机诞生interval = 0while True:if 用户是否点击关闭按钮退出程序breakinterval += 1if interval = 50 ...
 - 【干货】教你如何利用fullPage.js以及move.js插件打造高端大气的网站效果!
			
前言: 如今我们经常能见到全屏网站,尤其是国外网站.这些网站用几幅很大的图片或色块做背景,再添加一些简单的内容,显得格外的高端大气上档次. 在学习过jQuery插件之后,才发现之前的很多网站特效完全可 ...