跨域问题系列文章
1. 同源策略与CORS(跨域请求的起源)
2. SpringBoot2.x整合CORS解决跨域问题(两种方案)
3. 跨域预检请求进行权限认证(复杂跨域请求的处理)
4. Filter返回失败如何使用CORS配置(SendError和setStatus的区别)
CORS跨域资源访问,解决跨域问题就是修改Response
对象,添加对应的响应头完成的,在SpringBoot2.x中有两个配置可以完成设置。
1. 如何配置CORS
1. 在HandlerMapping中解决:
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
//.allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept", "X-Token", "content-type")
.allowedHeaders("*") //服务器允许的请求头
.allowedMethods("POST", "PUT", "GET", "OPTIONS", "DELETE") //服务器允许的请求方法
.allowCredentials(true) //允许带 cookie 的跨域请求
.allowedOrigins("*") //服务端允许哪些域请求资源
.maxAge(3600); //预检请求的缓存时间
}
}
源码:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
由上述配置可知,在RequestMappingHandlerMapping
完成了CORS的配置。请求会先执行Interceptor
链。若是请求在拦截器链中被拦截,直接返回,不经过DispatcherServlet进行处理,那么该配置不会生效。例如使用Response.setStatus返回响应码,该跨域配置就不会生效。
2. 在Filter中进行处理
CorsFilter
是SpringBoot
自带的一种Filter
,默认情况下没有在Spring
容器中配置,我们使用时,需要手动配置到容器中。
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
FilterRegistrationBean<CorsFilter> corsFilterFilterRegistrationBean = new FilterRegistrationBean<>();
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.setAllowedMethods(Arrays.asList("POST", "PUT", "GET", "OPTIONS", "DELETE"));
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setMaxAge(3600L);
source.registerCorsConfiguration("/**", corsConfiguration);
corsFilterFilterRegistrationBean.setFilter(new CorsFilter(source));
corsFilterFilterRegistrationBean.setOrder(-1);
return corsFilterFilterRegistrationBean;
}
需要注意:该拦截器的顺序。
例如在Shiro中,权限控制(认证和授权)是在ShiroFilter中完成的。而CorsFilter若在ShiroFilter之后,且ShiroFilter认证失败,是不会执行CorsFilter的配置的。我们在配置CorsFilter
时需要指定CorsFilter
优先级,让CorsFilter
优于ShiroFilter
。
2. 如何测试跨域
最简单的方式是在浏览器中输入:
$.ajax({
type: "POST",
url: "https://www.jianshu.com/p/7a191c19abc6",
contentType: 'application/json;charset=utf-8', //设置请求头信息
dataType: "json"
});