Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing CORs in SpringBootTest

Im trying to write a test to verify our CORS settings. I configure CORS like this.

@Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
//        super.configure(httpSecurity);
        httpSecurity.csrf().disable();
        httpSecurity.authorizeRequests().antMatchers("/**").permitAll();
        httpSecurity.cors();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        List<String> allowedMethods = CORS_ALLOWED_METHODS;
        configuration.setAllowedMethods(allowedMethods);
        configuration.setAllowedOrigins(CORS_ALLOWED_ORIGINS);
        configuration.setAllowedHeaders(CORS_ALLOWED_HEADERS);
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

I have verified with the debugger that CORS_ALLOWED_METHODS has values when my test runs.

Here is my test. It fails when I assert on the headers.

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("dev")
public class ControllerTests {

    @Autowired
    private WebApplicationContext wac;

    public MockMvc mockMvc;

    @Before
    public void setup() {
        DefaultMockMvcBuilder builder = MockMvcBuilders
                .webAppContextSetup(this.wac)
                .apply(SecurityMockMvcConfigurers.springSecurity())
                .dispatchOptions(true);
        this.mockMvc = builder.build();
    }

    @Test
    public void testCors() throws Exception {
        this.mockMvc
                .perform(get("/test-cors"))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(header().string("Access-Control-Allow-Methods", "OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE,CONNECT"))
                .andExpect(content().string("whatever"));
    }

    @SpringBootApplication(scanBasePackages = {"the.packages"})
    @Controller
    static class TestApplication {

        public static void main(String[] args) throws Exception {
            SpringApplication.run(TestApplication.class, args);
        }

        @RequestMapping(value = {"test-cors"},  method = RequestMethod.GET)
        @ResponseStatus(HttpStatus.OK)
        public @ResponseBody String testCors() {
            return "whatever";
        }
    }
}

As a note, when I actually run a SpringBoot app with this configuration we do get CORS headers.

Any help appreciated.

like image 419
hvgotcodes Avatar asked Mar 03 '17 21:03

hvgotcodes


People also ask

How do you test for CORS?

You can test it with any rest client like POSTMAN Rest Client, or simply you can check it from browser console - > Network tab -> in xhr filter - check the header for the particular request. you can check request and response.

Can I test CORS with Postman?

Postman simply doesn't care about CORS headers.

How do spring boots handle CORS?

To code to set the CORS configuration globally in main Spring Boot application is given below. Now, you can create a Spring Boot web application that runs on 8080 port and your RESTful web service application that can run on the 9090 port.


2 Answers

The CORS request needs to include an Origin header for the server to process it. The mock GET request is not having this header. The API does allow us to include headers in the mock requests.

public MockHttpServletRequestBuilder header(String name, Object... values)

Add a header to the request. Values are always added. Parameters: name - the header name values - one or more header values

Here is the code that works

.perform(options("/test-cors")
    .header("Access-Control-Request-Method", "GET")
    .header("Origin", "http://www.someurl.com"))

Both headers are required, and the configuration requires that allowed origins and methods align with the values passed in the test.

like image 109
Abhishek Avatar answered Sep 29 '22 01:09

Abhishek


Instead of initializing the CorsConfigurationSource Bean Simply initialize CorsFilter straight up. Just change that method like this and try,

@Bean
public CorsFilter corsFilter() {
        CorsConfiguration configuration = new CorsConfiguration();
        List<String> allowedMethods = CORS_ALLOWED_METHODS;
        configuration.setAllowedMethods(allowedMethods);
        configuration.setAllowedOrigins(CORS_ALLOWED_ORIGINS);
        configuration.setAllowedHeaders(CORS_ALLOWED_HEADERS);
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return new CorsFilter(source);
}

HTH!

like image 20
Sunand Padmanabhan Avatar answered Sep 29 '22 00:09

Sunand Padmanabhan