我有一个托管在公共 URL 上的 Web 应用程序,尝试调用本地 Web 服务 API(在本地主机上运行) 我正在使用 Chrome 访问公共网站,这会产生 CORS 问题,如此处所述
https://developer.chrome.com/blog/private-network-access-preflight/
上述链接中所述的解决方案是,
Spring CORS 尚不支持“Access-Control-Allow-Private-Network”标头。因此,我尝试了各种方法在我的 Spring Boot 应用程序中创建过滤器,但无济于事。过滤器永远不会被调用,我遇到了 CORS 问题。
请为我指出解决此问题的正确方向。
这是我的过滤器类
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("MyFilter invoked............");
final HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Private-Network", "true");
filterChain.doFilter(servletRequest, servletResponse);
}
}
这是我的配置类
@Configuration
public class MyConfig {
@Bean
public WebMvcConfigurer corsMappingConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
这并不能完全回答为什么你的代码不起作用,但我刚刚创建了一个 Spring 方法来实现这一点,所以它可能会对你有所帮助。我使用的是 Spring Boot 2.7,因此包含 Spring 5.3。
它使用自定义
CorsProcessor
类将相关标头添加到响应中。
CustomCorsProcessor.java
:
public class CustomCorsProcessor extends DefaultCorsProcessor implements CorsProcessor {
private static final String ACCESS_CONTROL_REQUEST_PRIVATE_NETWORK = "Access-Control-Request-Private-Network";
private static final String ACCESS_CONTROL_ALLOW_PRIVATE_NETWORK = "Access-Control-Allow-Private-Network";
@Override
public boolean processRequest(@Nullable CorsConfiguration config, HttpServletRequest request,
HttpServletResponse response) throws IOException {
//Allow DefaultCorsProcessor to run first
boolean superResult = super.processRequest(config, request, response);
if (superResult == false) return false;
ServerHttpRequest serverRequest = new ServletServerHttpRequest(request);
//If the CORS header requesting Private Network access is present, respond allowing access
if(serverRequest.getHeaders().containsKey(ACCESS_CONTROL_REQUEST_PRIVATE_NETWORK)) {
response.addHeader(ACCESS_CONTROL_ALLOW_PRIVATE_NETWORK, Boolean.toString(true));
}
return true;
}
}
您可能希望自定义
CorsConfiguration
类以避免对布尔值 true
进行硬编码。
然后
CustomCorsProcessor
类在 WebSecurityConfig
中用作 CorsProcessor
。
请注意,在此专用网络更改之前,
CorsConfigurationSource
本身就是@Bean
,但现在CorsFilter
是@Bean
。
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// by default uses a Bean by the name of corsFilter
.cors()
.and()
... as needed for your application
return http.build();
}
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.addAllowedOrigin("http://domain1.com");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public CorsFilter corsFilter() {
CorsConfigurationSource corsConfigurationSource = corsConfigurationSource();
CorsFilter corsFilter = new CorsFilter(corsConfigurationSource);
//Register our custom CorsProcessor that includes the Private Network allowed header
corsFilter.setCorsProcessor(new CustomCorsProcessor());
return corsFilter;
}
}
这允许 Chrome 连接到专用网络 Web 服务。
这部分基于我从这些 URL 中找到的内容:
https://spring.io/blog/2015/06/08/cors-support-in-spring-framework
https://www.baeldung.com/spring-cors
Spring 现在支持私域网 CORS:使用
allowPrivateNetwork
的 CorsRegistry
方法,例如这样:
import java.util.stream.Stream;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedMethods(
Stream.of(
HttpMethod.HEAD,
HttpMethod.GET,
HttpMethod.POST,
HttpMethod.PUT,
HttpMethod.DELETE,
HttpMethod.PATCH)
.map(HttpMethod::name)
.toArray(String[]::new))
.allowPrivateNetwork(true)
.allowedHeaders(
HttpHeaders.ACCEPT,
HttpHeaders.AUTHORIZATION,
HttpHeaders.CACHE_CONTROL,
HttpHeaders.CONTENT_TYPE);
}
}