1. 背景
首先解释一下同源策略:
同源策略,是由 Netscape 提出的一个著名的安全策略。现在所有支持 JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,子域名,协议,端口都相同。
早前浏览器会限制脚本中发起的跨域请求。比如,使用 XMLHttpRequest 对象发起 HTTP 请求就必须遵守同源策略。但是 HTML 的 <script>
标签是例外,可以突破同源策略从其他来源获取数据。利用这个特性,一些人想出了很 trick 的方式:JSONP。
但是,在当今的 Web 开发中,使用跨域 HTTP 请求加载各类资源(包括 JSON、CSS、图片、JavaScript 脚本以及其它类资源),已经成为了一种十分普遍的方式。所以 W3C 推荐了一种新的机制,即跨源资源共享(Cross-Origin Resource Sharing (CORS))。这种机制让 Web 应用服务器能支持跨站访问控制,从而使得安全地进行跨站数据传输成为可能。要使 XMLHttpRequest 在现代浏览器中可以发起跨域请求:
- 浏览器必须能支持跨源共享带来的新的组件,包括请求头和策略执行。
- 服务器端则需要解析这些新的请求头,并按照策略返回相应的响应头以及所请求的资源。
好在现代浏览器都已经支持 CORS 了,我们只需要在服务端处理跨域请求就可以。
结论:推荐使用 CORS2. jsonp
JSONP(JSON with Padding),并非新的数据格式,而是解决JSON跨域获取的解决方案。由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数,而数据就是传入回调函数中的JSON 数据。它主要利用了 <script/> 标签对 javascript 文档的动态解析。
实现步骤:
- 首先在客户端注册一个 callback , 然后把 callback 的名字传给服务器。
- 服务器先生成 JSON 数据。然后以 JavaScript 语法的方式,生成一个 function , function 名字就是传递上来的参数 callback。然后,将 JSON 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
- 最后,在客户端浏览器中解析 script 标签,并执行返回的 JavaScript ,此时数据作为参数,传入到了客户端预先定义好的回调函数里。
下面是具体实现代码:
2.1 前端
<script type="text/javascript">
function dosomething(jsondata){
//处理获得的json数据
}
</script>
<script src="http://example.com/data?callback=dosomething"></script>
jQuery 写法:
$.ajax({
url:"",
dataType:"jsonp",
data:{
params:""
}
}).done(function(data){
//dosomething..
})
仅仅是客户端使用 jsonp 请求数据是不够的,因为 jsonp 的请求是放在 script 标签中的,它请求到的是一段 js 代码,如果服务端返回了 json 字符串,那么浏览器就会报错。所以 jsonp 返回数据需要服务端做一些处理。
2.2 服务端
下面是 java 实现的 jsonp 的代码:
String callback = request.getParameter("callback");
String output = callback + "({ name : 'John', age : '19'});"
resp.setContentType("text/javascript");
PrintWriter out = resp.getWriter();
out.println(output);
// prints: jsonp1232617941775({"name" : "John", "age" : "19"}); withCredentials