跨域资源共享(CORS)是一种机制,用于控制对当前源之外的资源的AJAX调用。在某些情况下,您需要允许某些来源进行此类呼叫。例如,如果您有一个基于SAAS的产品,那么会有一些客户端连接到您的API并进行AJAX调用。
在Spring中,有几种方法可以检查传入请求的来源,方法,标头等。
您可以使用WebSecurityConfigurerAdapterSpring Security
的,并且WebMvcConfigurer
,@CrossOrigin
注释,CorsFilterSpring MVC
中。
我们正在提供基于SaaS的付款和钱包应用程序。我们正在通过JavaScript提供付款页面,因此有许多CORS请求来自我们的客户。在我们的案例中,我们需要动态更改允许的来源,因为可能会添加,删除或更新某些商家。
我们在此项目中的技术堆栈包括Spring Boot,Spring Cloud,Netflix OSS,而我们的网关是Netflix Zuul。
我以为在网关中过滤CORS请求是最佳选择,我开始查看Spring提供给我们的解决方案,然后选择在我们的一个Configuration类中创建一个CorsFilter bean。我们的配置如下。
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(clientService.getClientOrigins());
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
经过一些测试之后,我注意到,正如您所猜测的那样,在创建bean之后就无法更新允许的来源。因为CorsFilter的configSource属性是在创建bean时设置的,所以以后不能更改。
我复习了CorsFilter
课,然后看课里面有什么。它简单地扩展OncePerRequestFilter
,CorsConfigurationSource
在其构造函数中设置对象,并doFilterInternal
借助进行方法中的所有过滤DefaultCorsProcessor
。
我决定写我们CorsFilter
延伸OncePerRequestFilter
,利用DefaultCorsProcessor
处理CORS请求,做一样的事情CorsFilter确实在doFilterInternal
方法,并在运行时创建CorsConfiguration
。另外,我需要创建一个新服务并将其添加为依赖项,以从数据源动态获取来源。我创建了OriginService
类,该类从我们的数据源获取客户端的起源。我们的自定义cors过滤器的主要区别是在运行时通过OriginService
获取源来创建CorsConfiguration
。
我们的CustomCorsFilter类如下。
@Component
public class CustomCorsFilter extends OncePerRequestFilter {
@Autowired
OriginService originService;
private final CorsProcessor processor = new DefaultCorsProcessor();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
List<String> origins = originService.getOrigins();
config.setAllowedOrigins(origins);
config.setAllowedMethods(List.of("OPTIONS", "HEAD", "GET", "POST"));
config.addAllowedHeader("*");
source.registerCorsConfiguration("/**", config);
CorsConfiguration corsConfiguration = source.getCorsConfiguration(request);
boolean isValid = this.processor.processRequest(corsConfiguration, request, response);
if (!isValid || CorsUtils.isPreFlightRequest(request)) {
return;
}
filterChain.doFilter(request, response);
}
}
我们的CorsFilter确实在做我们想要的。更改客户的来源后,CorsConfiguration也将更改,并且开始对新的来源列表进行Cors过滤。
这是我们针对问题的解决方案,这种情况下可能会有一些不同且更简单的解决方案。但是我们的解决方案运行良好。可以更改类以实现非常灵活的配置。这取决于您的需求。
原文链接:http://codingdict.com