Spring Boot跨域问题
跨域请求
当我们从本身站点请求不同域名或端口服务所提供的资源时,就会发起跨域请求。
例如,我们最常见的我们很多的css样式文件是会链接到某个公共CDN服务器上,而不是在本身的服务器上,这其实就是典型的一个跨域骑牛。但浏览器由于安全原因限制了在脚本(script)中发起的跨域HTTP请求。也就是说XMLHttpRequest和Fetch等是遵循“同源规则”的,即只能访问自己服务器的指定端口的资源(同意服务器不同端口也会视为跨域)。但这种限制在今天,我们的应用需要访问多种API或资源的时候就不能满足开发者的需求了,因此就产生了若干对于跨域的解决方案,JSONP是其中一种,但在今天来看主流的更彻底的解决方案是CORS(Cross-Origin Resource Sharing)
跨域资源共享(CORS)
这种机制将跨域的访问控制权交给服务器,这样可以保证安全的跨域数据传输。现代浏览器一般会将CORS的支持封装在HTTP API之中(比如XMLHttpRequest和Fetch),这样可以有效控制使用跨域请求的风险。
概况来说,这个机制是增加一系列的HTTP头来让服务器可以描述哪些源是允许使用浏览器来访问资源的。而且对于简单的请求和复杂请求,处理机制是不一样的。
简单请求仅允许三个HTTP方法:GET,POST一级HEAD,另外只能支持若干header参数:Accept,Accept-Language,Content-Language,Content-Type(值只能是application/x-www-form-urlencoded、multipart/form-data 和 text/plain), DPR , Downlink , Save-Data , Viewport-Width 和 Width。
对于简单请求来说,比如下面这样一个简单的GET请求:从 http://me.domain 发起到 http://another.domain/data/blablabla 的资源请求
GET /data/blablabla/ HTTP/1.1
// 请求的域名
Host: another.domain
...//省略其它部分,重点是下面这句,说明了发起请求者的来源
Origin: http://me.domain
应用了CORS的对方服务器返回的响应应该像下面这个样子,当然这里 Access-Control-Allow-Origin: * 中的 * 表示任何网站都可以访问该资源,如果要限制只能从 me.domain 访问,那么需要改成 Access-Control-Allow-Origin: http://me.domain
HTTP/1.1 200 OK
...//省略其它部分
Access-Control-Allow-Origin: *
...//省略其它部分
Content-Type: application/json
那么对于复杂的请求怎么办?这需要一次预检请求和一次实际的请求,也就是说需要两次和对方服务器的请求/响应。预检请求是以option方法惊醒的,因为option方法不会改变任何资源,所以这个预检请求是安全的,它的职责在于发送实际请求将会使用的HTTP方法以及将要发送的header中将携带哪些内容,这样对方服务器可以根据预检请求的信息决定是否接受。
// 预检请求
OPTIONS /resources/post/ HTTP/1.1
Host: another.domain
...// 省略其它部分
Origin: http://me.domain
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
服务器对预检请求的响应如下:
HTTP/1.1 200 OK
// 省略其它部分
Access-Control-Allow-Origin: http://me.domain
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
// 省略其它部分
Content-Type: text/plain
接下来的正式请求就和上面的简单请求差不多了,就不赘述了。
在Spring Boot中启动CORS
在Spring Boot的启动类中加入下面的代码:
@Bean
@Order(Integer.MAX_VALUE)
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
// 设置你要允许的网站域名,如果全允许则设为 *
corsConfiguration.addAllowedOrigin("*");
// 如果要限制 HEADER 或 METHOD 请自行更改
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter();
}
如果加入上面的代码缺少jar包的话,在maven的pom文件中引入下面的依赖
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>java-property-utils</artifactId>
<version>1.9</version>
</dependency>
上一篇: spring boot 2.0 跨域问题
下一篇: HttpServlet