JavaScript 实现跨域的常用方法

  新手在练习Ajax的时候经常会出现“莫名其妙”的bug,代码都对,但是测试的时候控制台报错,原因可能就是测试文件路径有问题,导致了Ajax的跨域问题。跨域问题在开发过程中并不是很常见,但是还是有的,总结下常见的跨域访问的方法:

一、利用JSONP

<script type="text/javascript">
function handler(json-data) {
    //对获得的json数据进行处理
}
</script>
<script src="http://example.com/request.php?callback=handler"></script>

PS: 参数名可以不叫callback,但是一般都叫这个。

第二个script标签返回的内容会被当做JavaScript内容处理,所以服务器端可以这样写

<?php 
$callback = $_GET['callback'];  // 获得回调函数
$data = array('a','b','c');            // 数据
echo $callback.'('.json_encode($data).')'; // 拼接输出 相当于输出JS:callback(json-data);
?>

这样就能处理数据了。

jQuery可以这样写:

<script type="text/javascript">
$.getJSON('http://example.com/request.php?callback=?', function(json-data) {
    //处理数据
})
</script>

二、利用Window.domain

如果主页是http://www.example.com/a.html页面,iframe是http://example.com/b.html页面就会存在跨域问题:

<script type="text/javascript">
function onLoad() {
    var iframe = document.getElementById('iframe');
    var win = iframe.contentWindow; //这里能够获取到iframe的window对象,但是意义不大
    var doc = win.document; //这里获取不到iframe的document对象
    var doc = win.name; //同样获取不到windows对象的name
    ...
}
</script>
<iframe src="http://example.com/b.html" onload="onLoad()" id="iframe"></iframe>

解决方法:

我们只要把http://www.example.com/a.html 和http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的document.domain 可以设成a.b.example.com、b.example.com 、example.com中的任意一个,但是不可以设成 c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。

主页脚本:

<script type="text/javascript">
function onLoad() {
    document.domain = 'example.com';
    function test() {
        alert(document.getElementById('iframe').contentWindow);
    }
}
</script>
<iframe src="http://example.com/b.html" onload="test()" id="iframe"></iframe>

iframe脚本:

<script type="text/javascript">
document.domain = 'example.com';
</script>

三、利用window.name || location.hash

演示window.name,给name赋的值必须是字符串,而且大小不能太大,最大2M左右。如果需要传其他的数据可以转换成JSON字符串。

<!-- a页面的脚本,3s后跳转到b页面 -->
<script type="text/javascript">
window.name = '页面a设置的值';
setTimeout(function() {
    window.location = 'b.html';
}, 3000);
</script>

<!-- b页面的脚本 -->
<script type="text/javascript">
alert(window.name); //获取到window.name 的值
</script>

利用这个特性,同样认为所请求的页面数据和主页数据不同源:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>跨域</title>
<script type="text/javascript">
function getData() {
    var iframe = document.getElementById('proxy');
    iframe.onload = function() {
        var data = iframe.contentWindow.name;//iframe把数据放在了window.name里
        alert(data);
    };
    iframe.src = 'b.html';//不一定是b.html,只要和a.html同源即可,比如about:blank。这样iframe跳转到和a.html同源下,但是window.name没有发生改变,a.html就可以获取到!
}
</script>
</head>
<body>
    <!-- 不让iframe显现出来,iframe只是帮助跨域的 -->
    <iframe src="http://www.example.com/data.html" style="display: none;" onload="getData()" id="proxy"></iframe>
</body>
</html>

四、利用html5,postMessage()方法

<!-- http://test.com/a.html的代码 -->
<script type="text/javascript">
function onLoad(){
    var iframe = document.getElementById('iframe');
    var win = iframe.contentWindow;
    win.postMessage('我是 a 页面');
}
</script>
<iframe src="http://www.test.com/b.html" id="iframe" onload="onLoad()"></iframe>

<!-- http://www.test.com/b.html的代码 -->
<script type="text/javascript">
window.onmessage = function(e) {
    e = e || event;
    alert(e.data); //也可以从iframe发到window
};
</script>
五、CORS
这是服务器端允许脚本跨域,header("Access-Control-Allow-Origin: http://www.a.com"); 或者将请求发回服务器,然后让服务器完成请求再返回给客户端!
六、图像Ping
<script type="text/javascript">
var img = new Image();
img.onload = img.onerror = function() {
    alert('OK');
};
//之所以能把onload和error写成同一个事件,因为这种跨域方式是单向的,只能从客户端向服务器端发送数据而客户端接受不到服务器端的数据
img.src = "http://www.example.com/test?name=kiscall";
</script>

七、Comet

Comet有两种实现方式,长轮询和流。

短轮询:

长轮询:

服务器实现流的方法:

<?php 
    $i = 0;
    while(true) {
        echo "data";
        flush();
        sleep(10);
        $i++;
    }
?>

八、SSE和WebSockets就没时间介绍了!

 

注: 部分内容参考自http://www.cnblogs.com/2050/p/3191744.html

转载于:https://www.cnblogs.com/kiscall/p/4741801.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在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库来发送请求,并将请求发送到代理服务器上,代理服务器再将请求发送到目标服务器上。这样可以绕过浏览器的跨域限制。 以上是一些常用的解决跨域问题的方法,在实际应用中可以根据具体情况选择适合的方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值