0

I am attempting to connect my angular app to my new Spring Boot 2 controller. I start everything up and I get:

Access to XMLHttpRequest at 'localhost:8093/restapi/setup' from origin 'http://localhost:4200' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

Followed by:

ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "localhost:8093/restapi/setup", ok: false, …}

So this is CORS, right? When I hit localhost:8093/restapi/setup from postman, I get a valid response, as you'd expect.

So I do some research and especially I find this: No 'Access-Control-Allow-Origin' header is present on the requested resource—when trying to get data from a REST API

I finally find this article here:

https://chariotsolutions.com/blog/post/angular-2-spring-boot-jwt-cors_part1/

And that leads me to the following code:

@Configuration
public class ManageConfiguration {
    private static final Logger         LOGGER = LogManager.getLogger(ManageConfiguration.class);

    @Bean
    public CorsFilter corsFilter() {
        LOGGER.debug("Configuring CORS");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("DELETE");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

So I think this is straightforward and now try again and I get:

Access to XMLHttpRequest at 'localhost:8093/restapi/setup' from origin 'http://localhost:4200' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

Followed by:

ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "localhost:8093/restapi/setup", ok: false, …}

So it doesn't appear to make any difference whatsoever.

Checked and it's running on the right port:

2019-02-27 14:23:21.261  INFO 9814 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8093 (http) with context path ''

Made sure it included my CORS bean:

2019-02-27 14:23:19.608 DEBUG 9814 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'corsFilter'
...
o.springframework.web.filter.CorsFilter  : Filter 'corsFilter' configured for use

Per How can you debug a CORS request with cURL?, I did the following curl request to see my pre-flight stuff.

$ curl -H "Origin: http://example.com" --verbose http://localhost:8093/restapi/setup
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8093 (#0)
> GET /restapi/setup HTTP/1.1
> Host: localhost:8093
> User-Agent: curl/7.61.0
> Accept: */*
> Origin: http://example.com
> 
< HTTP/1.1 200 
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Access-Control-Allow-Origin: http://example.com
< Access-Control-Allow-Credentials: true
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 27 Feb 2019 21:38:28 GMT
< 
* Connection #0 to host localhost left intact
{"issueType":["bug","epic","subTask","task","story"]}

Been scratching my head for a day about what to try next and can't come up with anything. Suggestions?

Thom
  • 11,254
  • 22
  • 91
  • 152
  • 1
    It looks like in your frontend JavaScript code, you’ve just forgotten to include the 'https://' or 'http://' part in the request URL. See the answer at https://stackoverflow.com/questions/46258449/cors-error-requests-are-only-supported-for-protocol-schemes-http-etc/46258496#46258496 – sideshowbarker Feb 28 '19 at 10:36
  • @sideshowbarker Son of a *****! You were right on the money. I wondered why it was talking about protocols supported by CORS. Should have been a clue. You should post as an answer so I can give you credit. – Thom Feb 28 '19 at 12:10

3 Answers3

3

i think you're sending an ajax request without http:// protocol prefix in your request URL, try hitting http://localhost:8093/restapi/setup from ajax.

benjamin c
  • 1,930
  • 10
  • 22
1

Add this WebSecurityConfigurerAdapter in your code

import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

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

}

Also add the following WebMvcConfigurer

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfigurerImpl implements WebMvcConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**");
  }
}

At last add this annotation on top of your rest controller class : @CrossOrigin.

@CrossOrigin
public class RestController {
// Your methods
}

If you have a filter, you can add the following attributes to the response, if you don't have, you can use this one.

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Service;
import org.springframework.web.filter.OncePerRequestFilter;

@Service
public class JwtAuthenticationFilter extends OncePerRequestFilter {

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
    response.setHeader("Access-Control-Expose-Headers", "Content-Length, Authorization");
    filterChain.doFilter(request, response);
  }

}
Abhijay
  • 240
  • 1
  • 7
  • I don't have a filter, so I used the one you provided. I added the two classes you suggested and the @CrossOrigin annotation to my rest controller (which should be redundant). No change in behavior. – Thom Feb 27 '19 at 21:25
0
@Configuration
public class CorsConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
                        .allowedHeaders("*");
            }
        };
    }
}

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}

Please check the tutorial here https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

sankar
  • 256
  • 2
  • 14