您的位置:首页 > 编程语言 > Java开发

CORS的理解以及Spring Boot的配置方式

2018-02-06 21:06 471 查看

理解CORS

跨域访问其实是很正常的,比如,如果页面应用了CDN服务的资源,CDN资源的域名和后台服务器肯定不同,所以跨域没有什么问题。那为什么浏览器要提示:

已拦截跨源请求:同源策略禁止读取位于 http://xxxxx.com/account/cors 的远程资源。(原因:CORS 头缺少 ‘Access-Control-Allow-Origin’)。

这主要是浏览器出于对安全的考虑,缺省情况下,浏览器限制从脚本内发起的跨源HTTP请求。而目前我测试Safari, Firefox, Chrome浏览器,它们的动作实际是“限制”执行响应脚本,例如ajax的回调函数,在控制台,可以看到错误提示消息:



注意这里的“限制”,实际是限制请求成功调用执行结果,起到保护作用。

为什么是限制回调,而不是直接拦截呢?

我们需要明确CORS的限制不是在于你的主服务器是否允许访问其他站点,而是,其他站点是否允许你访问。就是,跨域限制是一种提供浏览器识别跨站点调用的网站是否允许当前站点调用。

加上taobao有一个数据服务器api接口,他只希望taobao的域名内的站点访问,那是不是其他站点就无法访问这些呢?如果按前面的理解:限制回调的过程,那么API的访问通过CORS是起不到防护作用的,因为数据实际上已经被浏览器接受,只是在浏览器内部的方法无法获得数据而已。

理解CORS,就是理解限制是在跨域的服务器端

Spring Boot如何实现跨域访问呢?

Spring boot提供了一个注解@CrossOrigin,如果在@RequestMapping的接口上应用后,该接口就可以被跨域访问了。这里是跨域访问。

如果需要实现全局(所有的API)都可以跨域访问,通过编写一个配置类即可实现:

@Configuration
public class MyConfiguration {

@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
}


更多的信息,请参考官方资料

OPTIONS请求

基于安全考虑,浏览器可能会发起“需预检的请求”,它要求首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。

所以后端必须实现接口的OPTIONS的响应,响应头需要包括允许跨域访问的消息头。

在Spring Boot中,CORS请求(包括预请求OPTIONS)都交给已注册的不同请求处理器(RequestMapping)处理。CorsProcessor(其缺省实现DefaultCorsProcessor)处理了预请求和CORS请求的处理。因此,对于CORS的处理,只需要做简单的工作就可以搞定。

添加@CorsCross注解到特定的方法或者控制器类,这样该接口或者该类所有接口都具有类跨域访问功能。

如果希望添加全局的功能,那么添加一个配置类即可:

@Configuration
public class CORSConfiguration {

@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("*")// 这个一定要调用
.allowedOrigins("*");
}
};
}

}


需要注意的是,使用WebMvcConfigurer配置时,一定要调用allowedMethods方法,不然,DELETE,PUT方法就具有CORS功能,浏览器跨域访问时就会出现403错误。

为什么一定要调用allowedMethods,并使用*来代替呢?因为缺省配置只保护GET, HEAD和POST方法。具体请看下面的源码:

public CorsConfiguration applyPermitDefaultValues() {
if (this.allowedOrigins == null) {
this.addAllowedOrigin(ALL);
}
if (this.allowedMethods == null) {
this.setAllowedMethods(Arrays.asList(
HttpMethod.GET.name(), HttpMethod.HEAD.name(), HttpMethod.POST.name()));
}
if (this.allowedHeaders == null) {
this.addAllowedHeader(ALL);
}
if (this.allowCredentials == null) {
this.setAllowCredentials(true);
}
if (this.maxAge == null) {
this.setMaxAge(1800L);
}
return this;
}


缺省只添加了GET, POST和HEAD方法,如果你刚好没有添加DELETE,PUT方法,那么CORS就会开始抱怨了。

参考:

HTTP访问控制(CORS)官方介绍

Spring RESTFull服务的CORS访问
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Spring