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 Boot 自动配置理解 以及实现自定义Starter
- SpringBoot配置Bean的两种方式--注解以及配置文件
- springboot读取自己定义的配置文件的方式以及使用joda_time来处理时间日期
- ajax跨域CORS方式JAVA Spring Boot配置
- spring boot框架学习学前掌握之重要注解(1)-sprng的java配置方式
- spring aop xml方式的配置案例 以及 annotation方式的配置aop
- redis在spring和springboot中的使用方式以及遇到的坑
- spring-boot 作为dubbo客户端 调用 dubbo 服务端 配置以及代码段
- 【笔记】 Spring Boot [ 3 ] 之命令行启动方式和激活不同的配置文件
- SpringBoot 简单文件上传实现以及jar包方式运行项目
- spring boot 在不同环境下读取不同配置文件的一种方式
- Spring-boot 配置Aop获取controller里的request中的参数以及其返回值
- Springboot打jar包分离lib配置文件正确方式
- Spring Boot全局支持CORS(跨源请求)的配置方法
- 【SpringBoot】java配置方式
- idea+Spring Boot的第一个应用,以及热部署的配置
- Bean作用域的配置以及 Spring各种注入方式实例 list set map props
- spring 中常用的两种事务配置方式以及事务的传播性、隔离级别
- Spring-boot中读取核心配置文件application和自定义properties配置文件的方式
- springboot 修改启动时默认加载application.properties文件以及加载指定配置文件