1. 什么是跨域问题
跨域是指一个域的文档或者脚本试图去请求另一个域下的资源。
跨域问题是指由于浏览器的同源策略(协议+域名+端口)限制,发送Ajax请求,获取cookies等行为在跨域的情况下会执行失败。
2.解决跨域问题的方法
- JsonP跨域
- iframe跨域
- nginx代理跨域
- websocket跨域
- 跨域资源共享(CORS)
目前最主流的跨域解决方案是CORS,也就是通过设置“Access-Control-Allow-Origin”系列请求头,来控制跨域请求,该解决方案所有浏览器都支持。
3.SpringBoot中解决跨域问题,包括OPTIONS请求
package www.jing.statistics.common.cors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
// 当前跨域请求最大有效时长。这里默认30天
private long maxAge = 30 * 24 * 60 * 60;
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
corsConfiguration.setMaxAge(maxAge);
corsConfiguration.setAllowCredentials(true); //用于 token 跨域
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); // 4 对接口配置跨域设置
return new CorsFilter(source);
}
}
到上一个步骤,已经可以解决普通跨域了。
但实际测试的情况下,发现当POST请求,Content-Type为"application/json"的时候,浏览器会发送一个OPTIONS的请求,这个请求当然肯定是404的,于是接口就请求失败了。
去查了一下,对于非简单的CORS请求(请求是PUT或者DELETE,或者Content-Type为application/json),会在正式通信前,增加一次HTTP查询请求,称之为预检请求(OPTIONS),只有预检请求(OPTIONS)发送成功后,浏览器才会发出正式的XMLHttpRequest请求。
这个问题在SpringBoot里也好办,在application.yml里配置
# 允许预检请求
spring:
mvc:
dispatch-options-request: true
重启服务后就可以访问OPTIONS请求了,到此跨域问题解决。