js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。
1. 简介
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
2. 请求过程
Preflight Request:
然后服务器端给我们返回一个Preflight Response
3. 通用实现
跨域请求分为两种情况,一种是cookie跨域一种是非cookie跨域
3.1 cookie跨域
3.1.1 服务端
只需要在方法中给response添加两个头信息即可
response.setHeader("Access-Control-Allow-Origin", "http://localhost:9105");
response.setHeader("Access-Control-Allow-Credentials", "true");
注意:
1)Access-Control-Allow-Origin是HTML5中定义的一种解决资源跨域的策略。他是通过服务器端返回带有Access-Control-Allow-Origin标识的Response header,用来解决资源的跨域权限问题。
2)Access-Control-Allow-Origin的value也可以是*,表示接受所有的跨域请求。
3)当Access-Control-Allow-Origin的value为*的时候,其所在的方法不能操作cookie
4)CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段。另一方面,开发者必须在AJAX请求中打开withCredentials属性。否则,即使服务器同意发送Cookie,浏览器也不会发送。或者,服务器要求设置Cookie,浏览器也不会处理。
5)Access-Control-Allow-Credentials头信息是可选设置,当其所在的方法不涉及对cookie的操作,那么这句话可以不写,同时客户端也不必添加({'withCredentials':true})
3.1.2 客户端(JS)
客户端的请求不变,但是需要加入一个对象信息({'withCredentials':true}),请求信息如下
$http.get("http://localhost:9107/cart/addGoodsToCartList.do?itemId="+$scope.sku.id+"&num="+$scope.num,{'withCredentials':true})
3.2 非cookie跨域
非cookie的实现比较简单,只需要在服务端添加如下头信息即可
response.setHeader("Access-Control-Allow-Origin", "http://localhost:9105");
注意:这里的域名可以用*代替,表示允许所有的跨域请求
4. SpringMVC跨域注解——CrossOrigin
springMVC的版本在4.2或以上版本,可以使用注解实现跨域, 我们只需要在需要跨域的方法上添加注解@CrossOrigin即可
@CrossOrigin有两个比较重要的属性
1)origins,对应于Access-Control-Allow-Origin
2)allowCredentials,对应Access-Control-Allow-Credentials
使用方法如下:
原理同上
1)当是cookie跨域的时候,两个属性都需要,且域名不能用*代替,但是,在MVC中,allowCredentials的缺省值就是true,所以,不管是cookie跨域还是非cookie跨域,都可以只写origins属性。
2)当是非跨域请求的时候,只需要origins属性即可,同时域名可以用*代替,表示所有的跨域请求