1、跨域原因
浏览器判断调用后台的地址和客户端地址不是同域地址,在正式调用后台接口前,会发送一个Option的请求到后台,在请求头里带上Access-Control-Request-Headers(调用接口即将带上的请求头)、Access-Control-Request-Method(调用接口将使用的Http方法)、Origin(客户端的域名)等信息。
后台需要返回积极的响应码,并在请求头里回复Access-Control-Allow-Origin(允许跨域访问的域名)、Access-Control-Allow-Methods(允许跨域调用的Http方法)、Access-Control-Allow-Headers(允许跨域访问的请求头)、Access-Control-Allow-Credentials(允许客户端携带验证信息,例如 cookie 之类的)等信息。请求和响应的信息一会了,浏览器才会正式对后端接口发起调用。
2、跨域解决方案
2.1 在nginx 统一处理option请求
在nginx统一处理option请求,这样option信息就不会打到后台应用进行处理。
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' '*';
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Access-Control-Max-Age' 1728000;
return 204;
}
2.2 使用@CrossOrigin
在Contoller类或者方法上加上@CrossOrigin,能起到针对对应的handler 加上跨域的配置。
这种情况再dispatchServlet 处理请求是,识别到是个cors请求,就会把HandlerExecutionChain 里的handler 替换成AbstractHandlerMapping.PreFlightHandler 处理这个请求。
2.3 增加CorsFilter 过滤器
在请求进入到intercepter、controller之前就进行处理。
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOriginPattern("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
2.4 重写WebMvcConfigurer 的addCorsMappings 方法
和@CrossOring 类似,是全局进行跨域配置。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("*")
.allowCredentials(true)
.allowedHeaders("*")
.maxAge(3600);
}
}