我有一个Spring Boot 2 REST API作为我的React应用程序的后端。该网站和API托管在不同的子域(分别为https://example.com
和https://api.example.com
)上,因此我设置了一个CORS过滤器来支持此操作:
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration apiCorsConfig = new CorsConfiguration();
apiCorsConfig.addAllowedOrigin("https://example.com");
apiCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
apiCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
apiCorsConfig.setMaxAge(600L);
source.registerCorsConfiguration("/**", apiCorsConfig);
FilterRegistrationBean filterRegistrationBean =
new FilterRegistrationBean<>(new CorsFilter(source));
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistrationBean;
}
这很好用。
我现在已经实现了Spring SAML以支持SAML,作为对API进行身份验证的另一种方法。所有SAML端点都位于/saml/**
下。 SAML身份验证请求可以来自任何来源,因此我需要打开这些终结点以允许来自任何来源的CORS请求。
我尝试了以下操作:
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration apiCorsConfig = new CorsConfiguration();
apiCorsConfig.addAllowedOrigin("https://example.com");
apiCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
apiCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
apiCorsConfig.setMaxAge(600L);
source.registerCorsConfiguration("/**", apiCorsConfig);
CorsConfiguration samlCorsConfig = new CorsConfiguration();
samlCorsConfig.addAllowedOrigin(CorsConfiguration.ALL);
samlCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
samlCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
samlCorsConfig.setMaxAge(600L);
source.registerCorsConfiguration("/saml/**", samlCorsConfig);
FilterRegistrationBean filterRegistrationBean =
new FilterRegistrationBean<>(new CorsFilter(source));
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistrationBean;
}
但是,这不起作用,并且当未知来源尝试访问403 Invalid CORS request
端点时会返回/saml/**
。
我想这里的问题是,即使存在与请求匹配的更具体的蚂蚁模式/**
,更通用的/saml/**
模式仍然优先。
我不想显式配置所有其他端点以允许网站起源,但希望它成为与任何其他CORS配置都不匹配的请求的全部。
如何允许任何来源访问/saml/**
,同时仍然只允许https://example.com
访问所有其他地点/**
?
答案 0 :(得分:2)
您可以扩展UrlBasedCorsConfigurationSource
并覆盖getCorsConfiguration
:
public class CustomeUrlBasedCorsConfigurationSource extend UrlBasedCorsConfigurationSource{
@Override
@Nullable
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
if(this.pathMatcher.match("/saml/**",lookupPath)){
return this.corsConfigurations.get("/saml/**");
}
return super.getCorsConfiguration(request);
}
您的配置应类似于:
@Bean
public FilterRegistrationBean corsFilter() {
CustomeUrlBasedCorsConfigurationSource source = new CustomeUrlBasedCorsConfigurationSource();
CorsConfiguration apiCorsConfig = new CorsConfiguration();
apiCorsConfig.addAllowedOrigin("https://example.com");
apiCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
apiCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
apiCorsConfig.setMaxAge(600L);
source.registerCorsConfiguration("/**", apiCorsConfig);
CorsConfiguration samlCorsConfig = new CorsConfiguration();
samlCorsConfig.addAllowedOrigin(CorsConfiguration.ALL);
samlCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
samlCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
samlCorsConfig.setMaxAge(600L);
source.registerCorsConfiguration("/saml/**", samlCorsConfig);
FilterRegistrationBean filterRegistrationBean =
new FilterRegistrationBean<>(new CorsFilter(source));
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistrationBean;
}
答案 1 :(得分:0)
通过将CorsConfiguration
添加到LinkedHashMap
内部的UrlBasedCorsConfigurationSource
中来注册它们。这意味着顺序会保留下来,只需要按照正确的顺序添加CorsConfiguration
即可:
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration samlCorsConfig = new CorsConfiguration();
samlCorsConfig.addAllowedOrigin(CorsConfiguration.ALL);
samlCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
samlCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
samlCorsConfig.setMaxAge(600L);
source.registerCorsConfiguration("/saml/**", samlCorsConfig);
CorsConfiguration apiCorsConfig = new CorsConfiguration();
apiCorsConfig.addAllowedOrigin("https://example.com");
apiCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
apiCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
apiCorsConfig.setMaxAge(600L);
source.registerCorsConfiguration("/**", apiCorsConfig);
FilterRegistrationBean filterRegistrationBean =
new FilterRegistrationBean<>(new CorsFilter(source));
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistrationBean;
}