I have a webapp hosted on a public URL, trying to call a local webservice API (running on localhost) I am using Chrome to access the public website, this creates a CORS issue as described here
https://developer.chrome.com/blog/private-network-access-preflight/
The solution stated in the above link is to either,
There is no Spring CORS support for the header "Access-Control-Allow-Private-Network" yet. So I have tried various ways to create a filter in my Spring Boot application, but to no avail. The filter never gets invoked and I encounter the CORS issue.
Please point me in the right direction to fix this issue.
This is my filter class
@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);
}
}
This is my config class
@Configuration
public class MyConfig {
@Bean
public WebMvcConfigurer corsMappingConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
This is not quite an answer to why your code does not work, but I have just created a Spring way to achieve this, so it may assist you. I am using Spring Boot 2.7 therefore Spring 5.3 is included.
It uses a custom CorsProcessor
class to add the relevant header to the response.
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;
}
}
You might like to customise the CorsConfiguration
class to avoid hardcoding the Boolean true
.
Then the CustomCorsProcessor
class is used in WebSecurityConfig
as a CorsProcessor
.
Note that before this Private Network change, the CorsConfigurationSource
was itself an @Bean
but now the CorsFilter
is the @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;
}
}
This then allowed Chrome to connect to the Private Network web service.
This is partly based on what I found from these URLs:
https://spring.io/blog/2015/06/08/cors-support-in-spring-framework
https://www.baeldung.com/spring-cors