CROS跨域
比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。
一、跨域访问抛出的异常
1). js跨域访问异常
如果被访问的服务器不设置相关跨域请求的头信息,浏览器会抛出入如下异常
XMLHttpRequest cannot load
...
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '...' is therefore not allowed access. The response had HTTP status code 400.
2). 跨域解决方案CORS
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
- 浏览器发送Preflight request
- 服务器响应Preflight Response
二、跨域案例演示
使用angularJS框架 + SpringMVC演示;这里只给出主要逻辑代码,其他知识点可以参照其我的其他文章!
推荐参考 :https://blog.csdn.net/u011050607/article/details/78385954
1). 前端的跨域js请求
- 需要添加参数
withCredentials:true
以携带cookie
// 跨域请求
$scope.cros = function () {
$http.get("http://localhost:9003/user/crostest.do",
{'withCredentials':true}).success(function (response) {
alert(response.message)
})
}
2). 后台的处理
- Access-Control-Allow-Origin:H5中定义的一种解决资源跨域的策略,通过服务器端返回带有Access-Control-Allow-Origin标识的Response header,用来解决资源的跨域权限问题
- 可以设置为
*
表示该资源谁都可以用(如果要使用Cookie,就不能使用通配符)
- 可以设置为
- CORS请求默认不发送Cookie和HTTP认证信息;如果需要,需要指定头信息
Access-Control-Allow-Credentials:true
;同时浏览器需要指定参数withCredentials:true
- SpringMVC跨域注解: 4.2版本之后可以添加注解
@CrossOrigin(origins = {"http://localhost:9105"},allowCredentials="true")
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private HttpServletRequest request;
@Autowired
private HttpServletResponse response;
@RequestMapping("/crostest")
// @CrossOrigin(origins = {"http://localhost:8086", "http://localhost:9105"}, allowCredentials = "true")
public Map addGoodsToCartList(Long itemId, Integer num) {
Map map = new HashMap();
// 设置允许跨域请求,指定可以跨域访问的域,可以进行逻辑处理访问指定的【域集合】;
final String[] ALLOW_DOMAIN = {"http://localhost:8086", "http://localhost:9105"};
String originHeader = request.getHeader("Origin");
if (!Arrays.asList(ALLOW_DOMAIN).contains(originHeader)) {
map.put("success", false);
map.put("message", "不被允许的跨域访问");
return map;
}
// 设置头响应头信息
response.setHeader("Access-Control-Allow-Origin", originHeader);
// 设置允许携带Cookie;如果如此设置,跨域设置就不能设置为通配符 *
response.setHeader("Access-Control-Allow-Credentials", "true");
// SpringMVC 4.2+ 可以使用注解实现跨域请求 @CrossOrigin 【可以设置多个,见上面注解部分】
map.put("success", true);
map.put("message", "允许的跨域访问");
return map;
}
}
3). NOTICE
案例中需要的一些知识点提示
- pom.xml中的fastjson依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
<scope>compile</scope>
</dependency>
- springmvc.xml中的注解扫描配置
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
<property name="features">
<array>
<value>WriteMapNullValue</value>
<value>WriteDateUseDateFormat</value>
</array>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>