用于访问控制允许专用网络的 Spring CORS 过滤器不起作用

问题描述 投票:0回答:2

我有一个托管在公共 URL 上的 Web 应用程序,尝试调用本地 Web 服务 API(在本地主机上运行) 我正在使用 Chrome 访问公共网站,这会产生 CORS 问题,如此处所述

https://developer.chrome.com/blog/private-network-access-preflight/

上述链接中所述的解决方案是,

  1. 在 Chrome 中禁用专用网络访问检查(有效)
  2. 设置响应标头“Access-Control-Allow-Private-Network: true”(不起作用)

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("/**");
            }
        };
    }
java spring-boot google-chrome cors private-network-access
2个回答
1
投票

这并不能完全回答为什么你的代码不起作用,但我刚刚创建了一个 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


0
投票

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);
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.