跨域资源共享
通过XMLHttpRequest实现ajax通信的时候有一个主要限制,来自于跨域安全策略。默认情况下,xhr对象只能访问到与包含它的页面位于同一个域中的资源。如果请求目标跨域,则会出现跨域问题:
下面的表格描述了在不同情况下允不允许跨域的情况:
URL 说明 是否允许通信
同一域名下 允许
同一域名下不同文件夹 允许
:8000/a.js 同一域名,不同端口 不允许
https://www.a.com/b.js 同一域名,不同协议 不允许
域名和域名对应ip 不允许
主域相同,子域不同 不允许
同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)
不同域名 不允许
(来自)
CORS(跨域资源共享)定义了在必须访问跨域资源时,浏览器和服务器应该如何沟通。CROS背后的思想就是使用自定义的HTTP头部让浏览器和服务器沟通,从而决定请求是否成功。 当浏览器给服务器发送请求时,其请求头部会包含一个头部信息:
这时,如果想让服务器接受这个请求,应该在Access-Control-Allow-Origin头部中回发想通的源信息,如:
Access: 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);
服务器:
(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);
服务器:
(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String callback = request.getParameter(“callback”);response.getWriter().write(callback + “({‘name’:’zhangsan’,’age’:’18’})”);}
却只能这样。只有对爱的人,我们才会斤斤计较,锱铢必较。