JavaScript跨域资源请求(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>
JavaScript跨域资源请求(CORS)解决方案的更多相关文章
- 004. 前端跨域资源请求: JSONP/CORS/反向代理
1.什么是跨域资源请求? https://www.cnblogs.com/niuli1987/p/10252214.html 同源: 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有 ...
- JSONP、图片Ping、XMLHttpRequest2.0等跨域资源请求(CORS)
跨域:当协议.主域名.子域名.端口号中任意一个不相同时都不算同一个域,而在不同域之间请求数据即为跨域请求.解决方法有以下几种(如有错误欢迎指出)以请求图片url为例: 1.通过XMLHttpReque ...
- .net MVC下跨域Ajax请求(CORS)
二.CROS (Cross-origin Resource Sharing) CROS相当于一种协议,由浏览器.服务端共同完成安全验证,进行安全的跨域资源共享.对于开发人员来说就跟在本站AJAX请求一 ...
- 跨域资源请求(除jsonp以外)的方法
---------------------------------------------------------------------------------------------------- ...
- JavaScript跨域调用、JSONP、CORS与ASP.NET Web API[共8篇]
[第1篇] 同源策略与JSONP 浏览器是访问Internet的工具,也是客户端应用的宿主,它为客户端应用提供一个寄宿和运行的环境.而这里所说的应用,基本是指在浏览器中执行的客户端JavaScript ...
- 跨域资源共享(CORS)在ASP.NET Web API中是如何实现的?
在<通过扩展让ASP.NET Web API支持W3C的CORS规范>中,我们通过自定义的HttpMessageHandler自行为ASP.NET Web API实现了针对CORS的支持, ...
- jsonp实现跨域资源访问
平时项目中处理ajax跨域资源请求时,例如www.example2.com上的某个页面要请求www.example1.com的数据,我们使用得较多的是jsonp方式.jsonp通过JavaScript ...
- thinkphp,javascript跨域请求解决方案
javascript跨域请求解决方案 前言 对于很多前端或者做混合开发的同学,我们难免会遇到跨域发起请求业务,比如A站点向B站点请求数据等等.由于最近要做一个站点集群的项目,所以具体业务要求很多个站点 ...
- 从零开始学 Java - Spring MVC 实现跨域资源 CORS 请求
论职业的重要性 问:为什么所有家长都希望自己的孩子成为公务员? 答:体面.有权.有钱又悠闲. 问:为什么所有家长都希望自己的孩子成为律师或医生? 答:体面.有钱.有技能. 问:为什么所有家长都不怎么知 ...
随机推荐
- Oracle 12c 多租户配置和修改 CDB 和 PDB 参数
1. 配置CDB 实例参数,影响CDB与所有 PDB为CDB配置例程参数相对于对于非CDB的数据库是变化不太.ALTER SYSTEM命令用于设置初始化参数,与使用ALTER DATABASE命令修改 ...
- [转]nodejs中的process模块--child_process.exec
1.process是一个全局进程,你可以直接通过process变量直接访问它. process实现了EventEmitter接口,exit方法会在当进程退出的时候执行.因为进程退出之后将不再执行事件循 ...
- 文件异步上传,多文件上传插件uploadify
本文中使用java作为例子 uploadify下载 http://files.cnblogs.com/chyg/uploadify.zip jsp页面中需要引入: <script type=&q ...
- Python-通过socket实现一个小型的端口检测工具
实验机器IP:192.168.220.139,端口开放情况 代码 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" import ...
- strust2.2.3版本启动报错struts-plugin.xml:8:162
我用的是struts-2.2.3,开始把全部的jar包都放进去了,可是一直报 信息: Parsing configuration file [struts-plugin.xml] 2011-6-11 ...
- USACO-Greedy Gift Givers(贪婪的送礼者)-Section1.2<2>
[英文原题] Greedy Gift Givers A group of NP (2 ≤ NP ≤ 10) uniquely named friends has decided to exchange ...
- Struts学习总结 学习
ContextMap 包含值栈包含 root(list结构)和context(map结构) 值栈包含contextMap的引用. Actioncontext是工具类 可以获取他们 Struts2拥 ...
- JS中apply和call的用法
JavaScript中有一个call和apply方法,其作用基本相同,但也有略微的区别. 先来看看JS手册中对call的解释: call 方法调用一个对象的一个方法,以另一个对象替换当前对象. cal ...
- EF Code first 和 DDD (领域驱动设计研究)系列一
在上个公司工作时,开发公司产品的过程中,接触到了EF Code first. 当时,整个产品的架构都是Lead developer设计建立的,自己也不是特别理解,就赶鸭子上架跟着一起开发了. 现在回过 ...
- 整数划分——真正的递归经典例题(NYOJ——90)
先注明学习博客的地址:(http://www.cnblogs.com/hoodlum1980/archive/2008/10/11/1308493.html) 题目描述:任何正整数n都可以写成n=n1 ...