403 Forbidden Spring Boot Web Socket Call

numerical25 picture numerical25 · Dec 2, 2015 · Viewed 12.6k times · Source

I am using Spring Boot 1.3.0.RELEASE. My code is based on the Starting Guide for websocket in Spring Boot using Stomp and SocketJS.

When I run the Client from localhost:8080 (Spring Server)... Of course it works. Its not until I try to call it from a Different Port, that I get a 403 Forbidden. My CorsFilter is set below.

Getting Started Web Sockets With Spring Boot

My Client is ....http://localhost:3000

My Spring Boot Server is ... http://localhost:8080

I setup my CorsFilter to access my client...

CorsFilter

package hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class CorsFilter implements Filter {

    private final Logger log = LoggerFactory.getLogger(CorsFilter.class);

    public CorsFilter() {
        log.info("SimpleCORSFilter init");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        String clientOrigin = request.getHeader("origin");
        response.addHeader("Access-Control-Allow-Origin", clientOrigin);
        response.setHeader("Access-Control-Allow-Methods", "POST, GET,  DELETE, PUT");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers",
                "Origin, Accept, X-Requested-With, Content-Type, " +
                        "Access-Control-Request-Method, Access-Control-Request-Headers");

        if (request.getMethod().equals("OPTIONS")) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }

}

Request Headers

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:localhost:8080
Origin:http://localhost:3000
Referer:http://localhost:3000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36

Response Headers

Access-Control-Allow-Credentials:true
Access-Control-Allow-Methods:POST, GET,  DELETE, PUT
Access-Control-Allow-Origin:http://localhost:3000
Access-Control-Max-Age:3600
Cache-Control:no-store, no-cache, must-revalidate, max-age=0
Content-Length:0
Date:Wed, 02 Dec 2015 13:59:25 GMT
Server:Apache-Coyote/1.1

Answer

Mr. Spice picture Mr. Spice · Jun 16, 2016

Adding an answer in case anyone else comes across this question. As suggested in the comments, you need to use the setAllowedOrigins method as described in the docs. So assuming that this is the tutorial you are following, you would end up with a configuration class that looks like this:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

  @Override
  public void configureMessageBroker(MessageBrokerRegistry config) {
    config.enableSimpleBroker("/your/topic");
    config.setApplicationDestinationPrefixes("/yourapp");
  }

  @Override
  public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/your/endpoint").setAllowedOrigins("http://localhost:3000").withSockJS();
  }

}

That would allow a stomp client running on localhost:3000 to subscribe to the /your/endpoint.