跨域资源共享
通过XMLHttpRequest实现ajax通信的时候有一个主要限制,来自于跨域安全策略。默认情况下,xhr对象只能访问到与包含它的页面位于同一个域中的资源。如果请求目标跨域,则会出现跨域问题:
下面的表格描述了在不同情况下允不允许跨域的情况:
URL | 说明 | 是否允许通信 |
---|---|---|
http://www.a.com/a.js http://www.a.com/b.js |
同一域名下 | 允许 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js |
同一域名下不同文件夹 | 允许 |
http://www.a.com:8000/a.js http://www.a.com/b.js |
同一域名,不同端口 | 不允许 |
http://www.a.com/a.js https://www.a.com/b.js |
同一域名,不同协议 | 不允许 |
http://www.a.com/a.js http://70.32.92.74/b.js |
域名和域名对应ip | 不允许 |
http://www.a.com/a.js http://script.a.com/b.js |
主域相同,子域不同 | 不允许 |
http://www.a.com/a.js http://a.com/b.js |
同一域名,不同二级域名(同上) | 不允许(cookie这种情况下也不允许访问) |
http://www.cnblogs.com/a.js http://www.a.com/b.js |
不同域名 | 不允许 |
(来自http://www.360doc.com/content/14/0522/23/9200790_380060755.shtml)
CORS(跨域资源共享)定义了在必须访问跨域资源时,浏览器和服务器应该如何沟通。CROS背后的思想就是使用自定义的HTTP头部让浏览器和服务器沟通,从而决定请求是否成功。
当浏览器给服务器发送请求时,其请求头部会包含一个头部信息:
Origin:http://localhost:63342
这时,如果想让服务器接受这个请求,应该在Access-Control-Allow-Origin头部中回发想通的源信息,如:
Access-Control-Allow-Origin: http://localhost:63342
如果想让任意域名都能访问,则可设置成*,以sevlet为例,调用response的setHeader即可:
response.setHeader("Access-Control-Allow-Origin", "*");
这样ajax再请求这个域名就不会出现跨域错误了。
JSONP
在CORS出现之前,也有很多办法实现跨域通信,JSONP是JSON with padding(填充式JSON或参数式JSON)的简写,利用了DOM中能够执行跨域请求的功能,在不依赖XMLHttpRequest对象的情况下也能发送某些请求。
因为script标签是可以跨域请求资源的,比如你能在localhost:8080/a.html里面去请求别的域名的文件比如<script src="http://code.jquery.com/jquery-1.11.1.min.js">
那么,又因为是脚本请求,服务器返回的数据是立即执行的,比如如果服务器返回的数据是alert(“hello”),那么客户端就会弹一个hello出来,如下
Javascript:
var script = document.createElement("script");
script.src = "http://localhost:8080/SaleHouse/Test";
document.body.appendChild(script);
服务器:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("alert(‘hello‘)");
}
执行js代码后,弹出hello对话框。
利用这一特性,我们可以让服务器将数据包装成一个函数,然后将服务器要传的数据传递到这个函数中,而这个数据用json格式是最合适不过了,像这样:
response.getWriter().write("handleResponse({‘name‘:‘zhangsan‘,‘age‘:‘18‘})");
这时,客户端请求到数据后会立即调用handleResponse方法,但是我们没有,没有就写一个呗
function handleResponse(resp){
//处理服务器的响应
console.log(resp.name + ":" + resp.age);
}
var script = document.createElement("script");
script.src = "http://localhost:8080/SaleHouse/Test";
document.body.appendChild(script);
为了处理更多数据,我们可以将函数名也作为参数传递给服务器,服务器动态返回要执行的函数,这就是JSONP。
Javascript:
function handleResponse(resp){
//处理服务器的响应
console.log(resp.name + ":" + resp.age);
}
var script = document.createElement("script");
//callback指定回调函数名
script.src = "http://localhost:8080/SaleHouse/Test?callback=handleResponse";
document.body.appendChild(script);
服务器:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String callback = request.getParameter("callback");
response.getWriter().write(callback + "({‘name‘:‘zhangsan‘,‘age‘:‘18‘})");
}
版权声明:本文为博主原创文章,未经博主允许不得转载。