跨域本身是个很简单的问题,到处都能找到相关的后台配置教程。多数都是如下,定义个filter,再把filter注册一下就好了。
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest httpRequest, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "5000");
response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, " +
"Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, Authorization, Token");
chain.doFilter(httpRequest, res);
}
}
@Bean
public FilterRegistrationBean corsFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new CorsFilter());
registration.addUrlPatterns("/*");
registration.setName("corsFilter");
registration.setOrder(1);
return registration;
}
问题就是前端在使用了axios后,即便后台加了上面的代码,会依旧反复出现跨域的问题,结果就是前端传过来的header中的Authorization,Content-Type等header参数丢失。
经过反复实验,发现每次axios都是先发OPTIONS请求,而非正常的GET、POST。由于我在Springboot的全局拦截器里设置有获取Authorization的地方,所以每次都鉴权失败。
后来经实验,发现了解决方式:
public class MvcInterceptor extends HandlerInterceptorAdapter {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public boolean preHandle(HttpServletRequest httpServletRequest,
HttpServletResponse response, Object handler) {
MutableHttpServletRequest httpRequest = new MutableHttpServletRequest(httpServletRequest);
//解决跨域
if ("OPTIONS".equals(httpRequest.getMethod())) {
return true;
}
//下面做你的鉴权功能
}
}
注册这个拦截器:
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MvcInterceptor());
}
}
主要原理就是在拦截器里,当Method是OPTIONS时,就直接return true就行了。