一、起源
当我们在开发前后端分离项目的时候,出于安全原因,浏览器禁止Ajax调用驻留在当前原点之外的资源。跨源资源共享(CORS)是由大多数浏览器实现的W3C规范,允许您灵活地指定什么样的跨域请求被授权,而不是使用一些不太安全和不太强大的策略,如IFRAME或JSONP。
二、如何解决跨域问题
方式一:使用@CrossOrigin注解
Spring Framework 4.2 GA为CORS提供了第一类支持,使您比通常的基于过滤器的解决方案更容易和更强大地配置它。所以springMVC的版本要在4.2或以上版本才支持@CrossOrigin
@CrossOrigin注解有两个参数
1、origins : 允许可访问的域列表
2、maxAge:准备响应前的缓存持续的最大时间(以秒为单位)。
@CrossOrigin(origins = "http://localhost:8082/",maxAge = 3600)
方式二:使用Spring内部的一种配置WebMvcConfigurer配置类(配置全局跨域)
需要创建一个配置类并实现WebMvcConfigurer 接口,这种方式的缺陷是,filter的顺序是固定的,在引入第三方组件的时候可能会因为filter滞后,导致出错
@Configuration
public class CrossOriginConfig implements WebMvcConfigurer {
//重新接口default方法解决跨越问题
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域的路径
registry.addMapping("/**")
// 设置允许跨域请求的域名
.allowedOrigins("*")
// 是否允许证书
.allowCredentials(true)
// 设置允许HTTP协议的8种请求类型,此处列举了6种
.allowedMethods("GET", "POST", "DELETE", "PUT","HEAD","OPTIONS")
// 设置允许的header属性
.allowedHeaders("*")
// 跨域允许时间
.maxAge(3600);
}
}
为什么要重写呢? 因为:一个类在实现接口中的default方法时,不知道应该实现哪一个default方法
查看源码我们可以看到,WebMvcConfigurer接口中定义了很多default修饰的方法。
一些常用的方法后续我们再研究:
//拦截器配置
void addInterceptors(InterceptorRegistry var1);
//静态资源处理
void addResourceHandlers(ResourceHandlerRegistry registry);
//视图解析器
void configureViewResolvers(ViewResolverRegistry registry);
//跨域问题
public void addCorsMappings(CorsRegistry registry) ;
方式三:Filter跨域请求过滤器
/**
* 解决跨域过滤器
*/
@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Credentials", "true");
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {
response.getWriter().println("ok");
return;
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}