1. SpringBoot的注解@CrossOrigin
@RestController
@CrossOrigin
@RequestMapping("")
public class TestController {
}
2. 处理跨域请求的Configuration
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").
allowedOriginPatterns("*"). // 重点。。允许跨域的域名,可以用*表示允许任何域名使用
// allowedOrigins("*"). //在Springboot2.4对应Spring5.3后在设置allowCredentials(true)的基础上不能直接使用通配符设置allowedOrigins,而是需要指定特定的URL。如果需要设置通配符,需要通过allowedOriginPatterns指定
allowedMethods("GET", "POST", "DELETE", "PUT") . //允许任何方法(post、get等)
allowedHeaders("*"). //允许任何请求头
allowCredentials(true). //带上cookie信息
exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果
}
}
3. 过滤器(filter)的方式
@Component
public class CoresFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");
filterChain.doFilter(servletRequest, servletResponse);
}
}
4. CorsConfiguration和UrlBasedCorsConfigurationSource
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 允许cookies跨域
config.setAllowCredentials(true);
// #允许向该服务器提交请求的URI,*表示全部允许,自定义可以添加多个,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin
config.addAllowedOrigin("*");
// #允许访问的头信息,*表示全部,可以添加多个
config.addAllowedHeader("*");
// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
config.setMaxAge(1800L);
// 允许提交请求的方法,*表示全部允许,一般OPTIONS,GET,POST三个够了
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//对所有接口都有效
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
5. 方法4 添加优先级
@Configuration
public class CorsConfig {
@Bean
public FilterRegistrationBean corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // 允许cookies跨域
config.addAllowedOrigin("*");// #允许向该服务器提交请求的URI,*表示全部允许,自定义可以添加多个,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin
config.addAllowedHeader("*");// #允许访问的头信息,*表示全部,可以添加多个
config.setMaxAge(1800L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
config.addAllowedMethod("*");// 允许提交请求的方法,*表示全部允许,一般OPTIONS,GET,POST三个够了
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);//对所有接口都有效
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); //注册到过滤器
bean.setOrder(Ordered.LOWEST_PRECEDENCE); // 优先级最高
return bean;
}
}
注意
config.setAllowCredentials(true);
设置cookie后 addAllowedOrigin 会报错 替换使用 addAllowedOriginPattern
遇到问题
当前后端分离时 使用shiro做权限过滤
@Bean
public FilterRegistrationBean delegatingFilterProxy() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
DelegatingFilterProxy proxy = new DelegatingFilterProxy();
proxy.setTargetFilterLifecycle(true);
proxy.setTargetBeanName(SHIRO_FILTER_NAME);
filterRegistrationBean.setFilter(proxy);
filterRegistrationBean.setAsyncSupported(true);
filterRegistrationBean.setEnabled(true);
//这里开始未设置优先级
filterRegistrationBean.setOrder(1);
filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
return filterRegistrationBean;
}
当验证token失效或者错误时候返回错误数据时候 前端总是会返回跨域问题。虽然设置跨域了但是失效。如果token验证正确 是可以请求到数据的
原因
添加过滤器的时候执行顺序错误
错误执行顺序shirofilter - corsfilter
如果shiro验证通过这样corsfilter会执行 跨域正常。
但是如果shiro验证失败返回错误 不会在走corsfilter的设置 这样前端会出现跨域问题。
解决办法修改执行顺序
corsfilter-shirofilter
让跨域设置优先执行
方法5可以设置执行顺序
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); //注册到过滤器
bean.setOrder(Ordered.LOWEST_PRECEDENCE); // 优先级最高
保险起见把shirofilter注册时候设置的比corsfilter大一些(其实没必要)
shirofilter
//这里开始未设置优先级
filterRegistrationBean.setOrder(1);
注意:@Order、Ordered不影响类的加载顺序而是影响Bean加载到IOC容器之后执行的顺序(优先级);
有文章说@Order 无效 (没有具体验证 设置过一次好像确实没管用)
直接使用注册到过滤器方式