跨域请求的经常使用方式及解释

同源策略

首先基于安全的缘由,浏览器是存在同源策略这个机制的,同源策略阻止从一个域加载的脚本去获取另外一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。这意味着浏览器隔离来自不一样源的内容,以防止它们之间的操做。html

js跨域是指经过js在不一样的域之间进行数据传输或通讯,好比用ajax向一个不一样的域请求数据,或者经过js获取页面中不一样域的框架中(iframe)的数据。前端

只要协议、域名、端口有任何一个不一样,都被看成是不一样的域。html5

 

下面介绍几种经常使用的跨域请求方式

默认端口为:8080jquery

1、利用jQuery获取jsonp

JSONP的原理与实现思路

1)Web页面调用js文件,可跨域。扩展:但凡是有src属性的标签都具备跨域能力。
2)跨域服务器 动态生成数据 并存入js文件(一般json后缀),供客户端调用。
3)为了便于客户端使用数据,造成一个非正式传输协议,称为JSONP。该协议重点是容许用户传递一个callback参数给服务器,而后服务器返回数据时 将此callback参数做为函数名包裹住JSON数据,使得客户端能够随意定制本身的函数来自动处理返回数据。ajax

 

 1.1若是咱们不用跨域请求的写法的话:json

复制代码
$('#cors1').click(function () {
    $.ajax({
        type:'get',
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});
复制代码

1.2使用跨越请求的写法,最简单的就是设置dataType:jsonp:后端

jsonp指定服务器返回的数据类型为jsonp格式,能够看发起的请求路径,自动带了一个callback=xxx,xxx是jquery随机生成的一个回调函数名称。跨域

这里的success默认success()做为回调函数。数据返回到前端后,就是success(result)的形式,由于是script脚本,因此自动调用success函数,而result就是success的参数。浏览器

复制代码
$('#cors1').click(function () {
    $.ajax({
        type:'get',
        dataType: 'jsonp',
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});
复制代码
复制代码
    @RequestMapping(value="/say", method = RequestMethod.GET)      //后端代码
    public String say(@RequestParam("callback") String callback){

        //callback前端传过来的回调函数名称

        //数据
        String result = "{age:22}";
        
        //用回调函数名称包裹返回数据,这样,返回数据就做为回调函数的参数传回去了
        result = callback + "(" + result + ")";
        return result;
        
    }
复制代码

 

1.3jsonpCallback

为jsonp请求指定一个回调函数名。这个值将用来取代jQuery自动生成的随机函数名。安全

调用回调函数的时候,先调用了指定的showData,而后再调用了success。

复制代码
$('#cors1').click(function () {
    $.ajax({
        type:'get',
        dataType: 'jsonp',   //指定服务器返回的数据类型 
        jsonpCallback: 'showData',    //指定回调函数名称
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});

function showData(data) {
    console.log("show"+data);
}
复制代码

1.4jsonp

在一个jsonp请求中重写回调函数的名字。这个值用来替代在"callback=?"这种GET或POST请求中URL参数里的"callback"部分,好比{jsonp:'onJsonPLoad'}会致使将"onJsonPLoad=?"传给服务器。

复制代码
$('#cors1').click(function () {
    $.ajax({
        type:'get',
        dataType: 'jsonp',
        jsonpCallback: 'showData',
        jsonp: 'sendParam',  //指定参数名称
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});

function showData(data) {
    console.log(data);
}
复制代码

指定jsonp后,后端也要改变:

复制代码
    @RequestMapping(value="/say", method = RequestMethod.GET)
    public String say(@RequestParam("sendParam") String sendParam){

        //sendParam前端传过来的回调函数名称

        //数据
        String result = "{age:22}";

        //用回调函数名称包裹返回数据,这样,返回数据就做为回调函数的参数传回去了
        result = sendParam + "(" + result + ")";
        return result;

    }
复制代码

 

 

1.5jsonp方式不支持POST方式跨域请求,就算指定成POST方式,会自动转为GET方式;然后端若是设置成POST方式了,那就请求不了了。

 

2、设置CORS头“Access-Control-Allow-Origin”

  •  CORS的原理:
     CORS定义一种跨域访问的机制,可让AJAX实现跨域访问。CORS 容许一个域上的网络应用向另外一个域提交跨域 AJAX 请求。实现此功能很是简单,只需由服务器发送一个响应标头便可。
 
复制代码
$('#cors1').click(function () {
    $.ajax({
        type:'get',
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});
复制代码
复制代码
    @RequestMapping(value="/say", method = RequestMethod.GET)
    public String say(HttpServletRequest request, HttpServletResponse response){
        //设置响应头
        response.setHeader("Access-Control-Allow-Origin","*");  //当前我设置的header为“*”,任意一个请求过来以后服务端咱们均可以进行处理&响应
    // 指定特定域名能够访问
       response.setHeader("Access-Control-Allow-Origin", "http:localhost:8080/")
//数据
        String result = "{age:22}";
        return result;
    }
复制代码

 

 

3、iframe+window.postMessage实现跨域

script、image、iframe的src都不受同源策略的影响。因此咱们能够借助这一特色,实现跨域。

postMessage()方法容许来自不一样源的脚本采用异步方式进行有限的通讯,能够实现跨文本档、多窗口、跨域消息传递。

 

发送消息

postMessage(data,origin)方法接受两个参数

 1.data:要传递的数据,html5规范中提到该参数能够是JavaScript的任意基本类型或可复制的对象,然而并非全部浏览器都作到了这点儿,部分浏览器只能处理字符串参数,因此咱们在传递参数的时候须要使用JSON.stringify()方法对对象参数序列化,在低版本IE中引用json2.js能够实现相似效果。

2.origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,因此能够不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,固然若是愿意也能够建参数设置为"*",这样能够传递给任意窗口,若是要指定和当前窗口同源的话设置为"/"。

<iframe id="ifr" src="http://localhost:8081/girl/b.html"></iframe>
window.onload = function () {
    var ifr = document.getElementById("ifr");
    ifr.contentWindow.postMessage("crsf","http://localhost:8081");
};

接收消息

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>testb</title>
</head>
<body>
    <div>b</div>
</body>
</html>
<script>
window.addEventListener('message', function(event){
console.log('origin: '+event.origin);    //origin: http://localhost:8080
console.log('data: '+event.data);      //data: crsf
console.log(event.source);
// 回发数据
event.source.postMessage('hello world', event.origin);
});
</script>
复制代码

有几个重要属性

  1. origin:发送消息窗口的源(协议+主机+端口号)
  2. data:顾名思义,是传递来的message
  3. source:发送消息的窗口对象

这样就能够接收跨域的消息了,咱们还能够发送消息回去。

 

 

出处:http://www.cnblogs.com/chaixiaozhi/p/8545462.html

相关文章
相关标签/搜索