Как сконфигурировать CORS для разных эндпоинтов?

Делал по этому примеру: https://bootcamptoprod.com/spring-boot-cors/#approach-2-using-a-webmvcconfigurer-bean

@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {

    @Value("${server.address}")
    private String uri;
    @Value("${server.port}")
    private int port;
    @Value("${external.payment-service}")
    private String externalURL;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        
        registry.addMapping("/bills/external")
                .allowedOrigins(externalURL)
                .allowedMethods(RequestMethod.OPTIONS.name(), RequestMethod.POST.name())
                .allowedHeaders("*")
                .exposedHeaders("*")
                .allowCredentials(true);

        registry.addMapping("/**")
                .allowedOrigins("http://" + uri +":" + port)
                .allowedMethods("*")
                .allowedHeaders("*")
                .exposedHeaders("*")
                .allowCredentials(true);
    }

}

@WebMvcTest(controllers = BankController.class)
class BankControllerTest {

    @Autowired
    private ObjectMapper mapper;

    @Value("${server.address}")
    private String uri;
    @Value("${server.port}")
    private int port;
    @Value("${external.payment-service}")
    private String externalURL;
    
    @Test
    void check_cors_protection() throws Exception {
        
        mockMVC.perform(options("/bills/external").header("Origin", externalURL))
            .andExpect(status().isOk());
            
        OperationRequest dto = new OperationRequest(777, 3, "USD", 100.01, "Demo");
        mockMVC.perform(post("/bills/external").header("Origin", externalURL)
                                                .content(mapper.writeValueAsString(dto)))
            .andExpect(status().isOk());
        
        mockMVC.perform(post("/bills/external").header("Origin", "http://" + uri +":" + port)
            .andExpect(status().isForbidden());
        
        mockMVC.perform(get("/bills/notify").header("Origin", externalURL))
            .andExpect(status().isForbidden());
        
        mockMVC.perform(get("/bills/notify").header("Origin", "http://" + uri +":" + port))
            .andExpect(status().isOk());    // FAILED TEST -> produces 403 instead of 200
    }
}

Почему-то работает только первый маппинг (см. последний вызов в тесте). Цель - иметь единый набор правил для всех эндпоинтов за исключением указанного в первом маппинге конфига, а у него чтобы был свой.


Ответы (1 шт):

Автор решения: V-CHO

Функционирует в случае создания всего этого хозяйства в основном конфиге с @EnableWebSecurity

    @Bean
    public WebMvcConfigurer corsBean() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                
                registry.addMapping("/bills/external")
                .allowedOrigins(externalURL)
                .allowedMethods(RequestMethod.OPTIONS.name(), RequestMethod.POST.name())
                .allowedHeaders("*")
                .exposedHeaders("*")
                .allowCredentials(true);

                registry.addMapping("/**")
                .allowedOrigins("http://" + uri +":" + port)
                .allowedMethods("*")
                .allowedHeaders("*")
                .exposedHeaders("*")
                .allowCredentials(true);
            }
        };
    }
→ Ссылка