user2270439 user2270439 - 1 year ago 110
React JSX Question

Spring No 'Access-Control-Allow-Origin' and no explicit mapping for /error for login page

I've been trying to create a login page in react in order to login on the spring backend I've created. However when I send the request to login I get the following error:

POST http://localhost:8080/login 403 ()


login:1 Fetch API cannot load http://localhost:8080/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 403. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.


I looked at the response headers and 'Access-Control-Allow-Origin' is indeed not present.

This is the request I'm doing:

fetch('http://localhost:8080/login', {
method: 'POST',
credentials: 'same-origin',
mode: 'cors',
headers: {
'Access-Control-Allow-Origin':'*',
Accept: 'application/xhtml+xml, application/xml, text/plain, text/html, */*',
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
},
body: {username: this.state.username, password: this.state.password}
})


My filter:

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request= (HttpServletRequest) servletRequest;

response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
//response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, Access-Control-Allow-Origin");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Max-Age", "180");
filterChain.doFilter(servletRequest, servletResponse);
}


Here's my security config:

protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(new CorsFilter(), SessionManagementFilter.class)
.authorizeRequests()
.antMatchers("/")
.permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.failureHandler(new CustomAuthenticationFailureHandler())
.successHandler(new CustomAuthenticationSuccessHandler())
.permitAll()
.and()
.logout()
.permitAll()
.and()
.httpBasic()
.and()
.csrf().disable();

}


I also get the following error when visiting localhost:8080/login directly:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Wed Aug 16 10:42:17 CEST 2017
There was an unexpected error (type=Not Found, status=404).
No message available

Answer Source

You are using the webpack server for the client, and a different server for your backend. For security purposes, the current web browsers don't allow cross domain request (your localhost:3000 is calling localhost:8080, two different domains).

There is two way to fix this:

  • Make a proxy from your webpack server to your backend server
  • Serve your client from your backend server

For the second option, I'll let you see how you could do it regarding the libraries you're using. Generally you need to define your backend routes match first, and then serve your client for all the default route (if you have a Single Page Application), or just serve your client for the "/" route.

For the proxy, you can see a detailed explanation on this blog post. Basically, since it seems you already have both of your servers running, it just a matter of adding this to your wepback config:

{
   ...
   "proxy": "http://localhost:3001/"
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download