Warek
Warek

Reputation: 1

Spring MVC two endpoints with the same path cause that OPTIONS request is not COSR safe

I'd like to prevent my REST API against cross-origin resource sharing. Unfortunately I stuck in some strange case connected with Spring MVC or Spring Boot.

In order to avoid blaming other libs I took clean Spring Boot 1.4 and recreated the problem.

1. Only one Endpoint /test

@RestController
@RequestMapping(value = "/test", produces = "application/v1")
public class Endpoint1 {

    @RequestMapping(method = RequestMethod.PUT)
    public void put() {
    }

}

Checki preflight cors request:

# Request
curl -I -X OPTIONS -H "Access-Control-Request-Method:PUT" -H "Origin:http://evilpage.com" -H "Accept: application/v2" localhost:8080/test

# Response
HTTP/1.1 403
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 20
Date: Thu, 06 Oct 2016 18:38:36 GMT

Everything is OK - CORS request is not possible. Header: Access-Control-Allow-Origin is not presented.

2. Two endpoints /test, versioned by Accept header

I have just added second endpoint with path /test.

@RestController
@RequestMapping(value = "/test", produces = "application/test2")
public class Endpoint2 {

    @RequestMapping(method = RequestMethod.PUT)
    public void put() {
    }

}

One more time check what OPTIONS request will return:

# Request
curl -I -X OPTIONS -H "Access-Control-Request-Method:PUT" -H "Origin:http://evilpage.com" -H "Accept: application/test2" localhost:8080/test

# Response
HTTP/1.1 200
Access-Control-Allow-Origin: http://evilpage.com
Vary: Origin
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Credentials: true
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 0
Date: Thu, 06 Oct 2016 18:40:41 GMT

... and something (Spring boot or mvc) sets Access-Control-Allow-Origin in response! Why?

Effect: browser ask my service (using preflight cors OPTIONS request) whether he can send PUT request over the origins. My service replay "no problem". PUT request, from difference origin, is handled by my service.

What I'd like to know:

  1. How is it possible? How does this mechanism works?
  2. How to prevent my API against that behaviour?

Thank You in advance for your help!

Code: https://github.com/wareq/sof-39903769/tree/master/src/main/java/com/warek - I have added only two classes with Endpoint definitions

Upvotes: 0

Views: 592

Answers (1)

Warek
Warek

Reputation: 1

I found out solution - registering filter direct to servlet. Hmm.. maybe there is better solution?

@Configuration
public class WebConfig {

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin(null);
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

Upvotes: 0

Related Questions