浏览器跨域系列(1) - 跨域和jsonp

跨域

跨域简单的说就是浏览器处于安全方面的考虑,基于浏览器的同源策略,不允许不同域之间相互请求资源…

背景

  • Ajax只能够在同域下请求资源(ajax只能提交json,xml,text,html等文件类型的数据,如果二进制文件就需要使用formData)
  • web页面上调用js文件时,不受是否跨域的影响(jsonp)

同源策略

域名组成
协议子域名主域名端口中任意一个不相同时,就是不同域的,那么这两个域需要交互,就是跨域的:
example
同源策略的限制包括:

  • 不能Ajax(同源数据请求方式)
  • 不能操作dom
  • 不能共享Cookie、LocalStorage、IndexedDB 等存储性内容

但是有三个标签是允许跨域加载资源

1
2
3
<img src=XXX>
<link href=XXX>
<script src=XXX>

跨域需求

一般进行跨域,都是基于两种需求:

  • 1.跨域数据通信(简单的说就是共享数据或者数据传递)
  • 2.跨域获取dom (例如获取iframe的高度)

JSONP(跨域获取数据)

  • 为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP;缺点是仅支持 get方法具有局限性。
  • 利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 数据
  • JSONP请求一定需要对方的服务器做支持才可以
  • 该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

总结

jsonp就是利用script标签可以不受浏览器同源策略的限制,通过get的方式跨域进行数据通信的方式,目前兼容型较好,但是只能支持get请求;目前jqery进行了封装

1.基本使用

在客户端

1
2
3
4
5
6
7
8
9
<script>
# 客户端根据指定的callback函数,定义对返回数据data的操作,例如alert出data的result属性
someCallBack(data){
// todo with data
alert(data.result);
}
</script>
# 在script标签中引入跨域请求的url,必须指定callback给一个函数(必须),也可以传入其他参数(非必须)
<script src="www.crossDomainServer.com/remote.js?callback='someCallBack'&userName='unclePis'"></script>

在服务器端,只需要使用传入的函数将需要返回的json数据包裹返回就好,例如

1
someCallBack({name:'root',password:'1233211234567'})

这样在客户端就相当于加载了一个js文件,调用定义好的函数

1
2
3
4
5
6
7
8
9
   <script>
# 函数声明
someCallBack(data){
# todo with data
alert(data.result);
}
# 函数调用
someCallBack({name:'root',password:'1233211234567'})
</script>

2.动态添加

1
2
3
4
5
6
7
8
9
var someCallBack = function(data){
# todo with data
alert(data.result);
}
var script = document.createElement('script');
var src = "www.crossDomainServer.com/remote.js?callback='someCallBack'&userName='unclePis'";
script.setAttribute('src', url);
# 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);

3.jQuery的jsonp形式

简单的说,jquery的dataType为jsonp的时候,就帮你封装了上面的基本实现,你只需要在success里面处理数据的返回就ok了,感觉好像ajax在同域请求资源一样

1
2
3
4
5
6
7
8
9
10
11
12
$.ajax({
url:"http://crossdomain.com/jsonServerResponse",
dataType:"jsonp",
type:"get", # 可以省略,JSONP都是GET
jsonpCallback:"fn",# ->自定义传递给服务器的函数名,而不是使用jQuery自动生成的,可省略
jsonp:"jsonp",# ->把传递函数名的那个形参callback变为jsonp,可省略
success:function (data){
console.log(data);}
}),
error: function(){
alert('fail');
}

JSONP和AJAX对比

  • JSONP和AJAX相同,都是客户端向服务器端发送请求,从服务器端获取数据的方式
  • 但AJAX属于同源策略,JSONP属于非同源策略(跨域请求)

其他

跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。

参考文章

跨域几种方式
jsonp原理详解——终于搞清楚jsonp是啥了

初到贵宝地,有钱的给个钱场,没钱的挤一挤给个钱场