javascript解决跨域的六种方法

在客户端编程语言javascript,同源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法。只有当两个域具有相同的协议,相同的主机,相同的端口时,我们就认定他们是相同的域。可是在实际开发中我们经常需要获取其他域的资源,这个时候各种不同的跨域资源方式就各显神通了,今天主要来总结一下工作中常用的几种跨域方式,以备查询。

1.window.name

window 对象的name属性是一个很特别的属性,当在 frame 中加载新页面时,name 的属性值依旧保持不变。那么我们可以在页面 A中用iframe加载其他域的页面B,而页面B中用JavaScript把需要传递的数据赋值给window.name,iframe加载完成之后,此时 name 属性值可被获取到,以访问 Web 服务发送的信息。但 name 属性仅对相同域名的 frame 可访问。这意味着为了访问 name 属性,当远程 Web 服务页面被加载后,必须导航 frame 回到原始域。即页面A修改iframe的地址,将其变成同域的一个地址,然后就可以读出window.name的值了。一旦 name 属性获得,销毁 frame 。这个方式非常适合单向的数据请求,而且协议简单、安全。

页面B代码如下:

<script type="text/javascript"> window.name = 'I was there!'; // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右 // 数据格式可以自定义,如json、字符串 </script>

页面A代码如下:

<script type="text/javascript">
 var state = 0;
 iframe = document.createElement('iframe');
 loadfn = function {
 if (state === 1) {
 var data = iframe.contentWindow.name; // 读取数据
 console.log(data); //弹出'I wasthere!'
 (function{ //获取数据以后销毁这个iframe。 
iframe.contentWindow.document.write('');
 iframe.contentWindow.close; 
document.body.removeChild(iframe);
 }); 
} else if (state === 0) {
 state = 1; // 设置的代理页面使其回原始域
 iframe.contentWindow.location = "http://www.jack.com/proxy.html";
 }
 };
 iframe.src = 'http://www.jesse.com/data.html';
 if (iframe.attachEvent) {
 iframe.attachEvent('onload', loadfn);
 } else { 
iframe.onload = loadfn;
 }
 document.body.appendChild(iframe); 
</script>

2.具备src的标签

虽然浏览器默认禁止了跨域访问,但并不禁止在页面中用标签的src属性引用其他域的文件。根据这一点,可以方便地通过创建具有src属性的节点方法来实现完全跨域的通信。使用这种原理的跨域方式有以下几种:

动态创建script

例如我要从域A的页面pageA加载域B的数据,那么在域B的页面pageB中我以JavaScript的形式声明pageA需要的数据,然后在 pageA中用script标签把pageB加载进来,那么pageB中的脚本就会得以执行。

pageA代码如下:

function getData(data){ //这里是对获取的数据的相关操作 console.log(data); 
//数据获取到后移除创建的script标签 
document.body.removeChild(originData);
 } 
var originData = document.createElement('script'); 
originData.src = 'http://www.jesse.com/data.js'; 
originData.setAttribute("type", "text/javascript"); 
document.body.appendChild(originData);

pageB代码如下:

getData('这里是远程跨域获取的数据');//数据格式可以自定义,如json、字符串

jsonp

在用$.ajax获取远程数据时,如果是跨域资源则可以使用jsonp方法,以前一直以为jsonp是ajax的一种,后来才明白他们根本就不是一回事。ajax是以xhr方式请求数据的,而jsonp是以script方式请求数据的,这个就是和上面的动态创建script方式一样。 pageA

代码如下:

$.ajax({ //JSONP不支持POST方式 
type:"GET",
 url:"http://www.jesse.com/data.php", 
dataType:"jsonp", //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据 jsonpCallback:"getData", 
success: function(data){ 
console.log(data);
 }, 
error: function{ console.log('fail'); } 
})

pageB代码如下:

<?php $callback = $_GET['callback'];//得到回调函数名,这里是getData $data = array('a','b','c');//要返回的数据 echo $callback.'('.json_encode($data).')';//输出 ?>

3.document.domain

对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。 

具体的做法是可以在a.html和http://script.a.com/b.html两个文件中分别加上 document.domain = "a.com";

然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以 “交互”了。当然这种办法只能解决主域相同而二级域名不同的情况 上的a.html

document.domain = 'a.com';
 var ifr = document.createElement('iframe');
 ifr.src = 'http://script.a.com/b.html'; 
ifr.style.display = 'none';
 document.body.appendChild(ifr); 
ifr.onload = function{ 
var doc = ifr.contentDocument || ifr.contentWindow.document; // 在这里操纵b.html 
alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue); };

script.a.com上的b.html

document.domain = 'a.com';

4.跨域资源共享(CORS)

原理:跨源资源共享(CORS)定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS允许一个域上的网络应用向另一个域提交跨域AJAX请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。它是通过客户端+服务端协作声明的方式来确保请求安全的。服务端会在HTTP请求头中增加一系列HTTP请求参数(例如Access-Control-Allow-Origin等),来限制哪些域的请求和哪些请求类型可以接受,而客户端在发起请求时必须声明自己的源(Orgin),否则服务器将不予处理,如果客户端不作声明,请求甚至会被浏览器直接拦截都到不了服务端。服务端收到HTTP请求后会进行域的比较,只有同域的请求才会处理。

pageA代码如下:

var xhr = new XMLHttpRequest; 
xhr.onreadystatechange = function{ 
if(xhr.readyState === 4 && xhr.status === 200){
 console.log(xhr.responseText);
 }
 }; 
xhr.open("get","http://www.jesse.com/data.php");
 xhr.send(null);

pageB代码如下:

<?php
 header("Access-Control-Allow-Origin: http://www.jack.com");//与简单的请求相同
 header("Access-Control-Allow-Methods: GET, POST");//允许请求的方法
 header("Access-Control-Max-Age: 3628800"); //将这个请求缓存多长时间
 $data = array('a','b','c');//要返回的数据 
echo json_encode($data);//输出
 ?>

5.window.postMesage 不常用

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

<iframe id="proxy" src="http://www.jesse.com/index.html" onload="postMsg" style="display: none"></iframe>
 <script type="text/javascript"> 
var obj = { msg: 'hello world' } 
function postMsg { 
var iframe = document.getElementById('proxy');
 var win = iframe.contentWindow;
 win.postMessage(obj, 'http://www.jesse.com');
 } 
</script>

pageB代码如下:

<script type="text/javascript">
 window.onmessage = function(e) { console.log(e.data.msg + " from " + e.origin); }
 </script>

6. location.hash 不常用

pageA代码如下:

function startRequest { 
var ifr = document.createElement('iframe');
 ifr.style.display = 'none'; 
ifr.src = 'http://www.jesse.com/b.html#sayHi'; //传递的
location.hash document.body.appendChild(ifr); 
function checkHash {
 try {
 var data = location.hash ? location.hash.substring(1) : '';
if (console.log) { 
console.log('Now the data is ' + data);
 } 
} catch (e) {};
 } 
setInterval(checkHash, 5000); 
window.onload = startRequest;

pageA代码如下:

parent.parent.location.hash = self.location.hash.substring(1);

pageB代码如下:

function checkHash { var data = ''; //模拟一个简单的参数处理操作 
switch (location.hash) {
 case '#sayHello': 
data = 'HelloWorld'; break; 
case '#sayHi': data = 'HiWorld'; break; default: break;
 } 
data && callBack('#' + data);
 } 
function callBack(hash) { // ie、chrome的安全机制无法修改parent.location.hash,所以要利用一个中间的www.a.com域下的代理iframe var proxy = document.createElement('iframe'); 
proxy.style.display = 'none'; 
proxy.src = 'http://www.jack/c.html' + hash; // 注意该文件在"www.jack.com"域下
 document.body.appendChild(proxy);
 }
 window.onload = checkHash;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Java和JavaScript中,可以使用以下方法解决跨域问题: 1. 服务器端设置响头:在Java中,可以在服务器端设置响应头来允许跨域访问。在处理请求的方法或过滤器中,添加以下响应头: ``` response.setHeader("Access-Control-Allow-Origin", "*"); ``` 这将允许所有域名的请求访问服务器资源。如果希望仅允许特定域名的请求,将`*`替换为相应的域名。 2. JSONP(仅限GET请求):JSONP是一种利用<script>标签进行跨域请求的方法。在JavaScript中,可以创建一个动态的<script>标签,设置其src属性为包含回调函数的URL。服务器端返回的响应结果将被当作JavaScript代码执行,并通过回调函数传递给客户端。 3. CORS(跨域资源共享):CORS是一种通过在请求头中添加特定字段来实现跨域请求的机制。在Java中,可以通过使用`javax.servlet.Filter`来处理CORS请求。创建一个实现`javax.servlet.Filter`接口的类,在`doFilter`方法中添加以下代码: ```java response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); ``` 这将允许所有域名的GET、POST、PUT和DELETE请求访问服务器资源,并设置了允许的请求头字段。 4. 代理服务器:如果以上方法无法解决跨域问题,可以考虑使用代理服务器。在Java中,可以使用Apache HTTP客户端或HttpClient库来发送请求,并将请求发送到代理服务器上,代理服务器再将请求发送到目标服务器上。这样可以绕过浏览器的跨域限制。 以上是一些常用的解决跨域问题方法,在实际应用中可以根据具体情况选择适合的方法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值