Notes on cross domain access processing of springboot web project

Posted by d.shankar on Sat, 25 Apr 2020 16:29:18 +0200

Solve the problem of cross domain access of spring MVC web project

1. Cross origin cross domain annotation
springboot has its own cross domain annotation, which can be placed on the RestController's class or method. It can also customize those domain names, which can be cross domain and very flexible
@CrossOrigin / / by default @ CrossOrigin allows all sources and HTTP methods specified in the @ RequestMapping annotation
@CrossOrigin(origins = "*", allowedHeaders = "*")
@CrossOrigin(origins = "http://domain-2.com", allowedHeaders = "Access-Control-Allow-Headers, Content-Type, Accept, X-Requested-With, remember-me", maxAge = 3600)

2. Filter mode

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@Component
public class MyCorsFilter implements Filter {

    public MyCorsFilter() {
        log.info(">>>>>> MyCorsFilter init");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        if (request.getHeader("Origin") != null) {
            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        } else {
            response.setHeader("Access-Control-Allow-Origin", "*");
        }
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
        chain.doFilter(req, resp);
    }

    @Override
    public void init(FilterConfig filterConfig) {

    }

    @Override
    public void destroy() {

    }
}

3. Global CORS configuration in addcorsmapping method of Web MVC Configuration
1)WebMvcConfigurationSupport

@Slf4j
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurationSupport {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        super.addCorsMappings(registry);
        registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS");
    }
}

2)WebMvcConfigurerAdapter
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS");;
    }
}

3)WebMvcConfigurer
@Slf4j
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS");
    }
}

4) If you are using Spring Security, make sure that CORS is enabled at the Spring Security level to allow it to take advantage of the configuration defined at the Spring MVC level.

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()...
    }
}

5) CorsConfiguration and CorsFilter

@Configuration
public class CorsConfig {

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1 allow any domain name to use
        corsConfiguration.addAllowedHeader("*"); // 2 any head is allowed
        corsConfiguration.addAllowedMethod("*"); // 3 allow any method (post, get, etc.)
        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); 
        return new CorsFilter(source);
    }
}

or

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("http://domain-1.com");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>();
    bean.setFilter(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
}

You can easily change any property and apply this CORS configuration only to specific path patterns:

@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/api/**")
        .allowedOrigins("http://domain-2.com")
        .allowedMethods("GET","POST","PUT","DELETE","OPTIONS")
        .allowedHeaders("header1","header2","header3")
        .exposedHeaders("header1","header2")
        .allowCredentials(false)
        .maxAge(3600);
}

4. XML namespace
CORS can be configured using the mvc XML namespace.
This minimal XML configuration enables CORS in the / * * path mode, with the same default properties as JavaConfig:

<mvc:cors>
    <mvc:mapping path="/**" />
</mvc:cors>

You can also declare multiple CORS mappings using custom attributes:

<mvc:cors>
    <mvc:mapping path="/api/**"
        allowed-origins="http://domain-1.com,http://domain-2.com"
        allowed-methods="GET","POST","PUT","DELETE","OPTIONS"
        allowed-headers="header1,header2,header3"
        exposed-headers="header1,header2" 
        allow-credentials="false"
        max-age="3600" />
    <mvc:mapping path="/resources/**" allowed-origins="http://domain1.com" />
</mvc:cors>

Topics: Programming Spring xml SpringBoot Lombok