7

I've looked at other questions on the site similar to this and despite doing those resolutions, my issue remains the same.

Side note, I also tried setHeader(clientOrigin)

I am using Spring Boot v1.2.7.RELEASE and The Spring Console is what is telling me that Origin Header Value not allowed. My client returns with a 403 forbidden.

CorsFilter

package app.config;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@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", "Accept, Content-Type, Origin, Authorization, X-Auth-Token");
        response.addHeader("Access-Control-Expose-Headers", "X-Auth-Token");

        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 Header

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

Response Headers

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Accept, Content-Type, Origin, Authorization, X-Auth-Token
Access-Control-Allow-Methods:POST, GET,  DELETE, PUT
Access-Control-Allow-Origin:http://192.168.1.66:8105
Access-Control-Expose-Headers:X-Auth-Token
Access-Control-Max-Age:3600
Cache-Control:no-store, no-cache, must-revalidate, max-age=0
Content-Length:0
Date:Sat, 28 Nov 2015 23:49:56 GMT
Server:Apache-Coyote/1.1

The call I am trying to make is a SocketJS call and its a get call. The following script is being called.

var socket = new SockJS($scope.siteUrl+'/connect?TOKEN='+$localstorage.get('X-AUTH-TOKEN-TRIVIA'));
    $scope.stompClient = Stomp.over(socket);
    $scope.stompClient.connect({"Authorization":"TOKEN" }, function(frame) {
        console.log('Connected: ' + frame);
        stompClient.subscribe($scope.siteUrl+'/socketupdate', function(greeting){
            $scope.activegame = JSON.parse(greeting.body).content;
        });
    });

As you can see, I am passing the token as a query string because for some strange reason SocketJS does not allow me to pass the X-AUTH-TOKEN via header.

My client server is however on a different port. I am building an app utilizing ionic which is a angular based framework.

I notice that the error comes from my WebSocketService

2015-11-29 03:22:32.417  WARN 33932 --- [nio-8080-exec-1] o.s.w.s.s.t.h.DefaultSockJsService       : Origin header value 'http://192.168.1.66:8105' not allowed.

would this mean I have to set something in the WebSocketConfig that will accept this ??

numerical25
  • 10,524
  • 36
  • 130
  • 209
  • 1
    What told you that it was an illegal request (firefox I guess) and which method is the request? Btw, if you use the most recent version of spring (4.2) you only need to add [`@CrossOrigin`](https://spring.io/blog/2015/06/08/cors-support-in-spring-framework) to method you want to allow.. – zapl Nov 29 '15 at 00:03
  • I am using Spring Boot v1.2.7.RELEASE Not sure what version of Spring is wrapped in that. Spring is telling me this in the console on the server and it returns a 403 forbidden. Also I do not see a annotation for @CrossOrigin – numerical25 Nov 29 '15 at 00:08
  • The annotation requires Boot 1.3 or [manually](http://blog.codeleak.pl/2015/09/override-spring-framework-version-in.html) upping the framework version to 4.2, the 1.2 Boot versions use spring 4.1 by default. – zapl Nov 29 '15 at 00:33
  • I haven't tested this with Spring Boot, but you can use this library to add CORS support to versions of Spring prior to 4.2: https://github.com/Russell-Allen/CrossOrigin – allenru Nov 29 '15 at 03:50
  • I see what your saying. But to my knowledge. I thought `response.addHeader("Access-Control-Allow-Origin", clientOrigin);` should achieve the same goal. Its pretty much finding the origin url and giving it access. If not this, then shouldnt I be able to allow cross origin from the CORSFilter ? Ive also updated my post to include the SOCKJS java script i am using to make the call – numerical25 Nov 29 '15 at 07:37
  • Your quickest resolution is to upgrade to the latest version of SpringBoot which uses Spring 4.2, and has built in CORS support (as zapl suggested.) If you look at the JavaDoc for DefaultSockJsService between the version you're on and the latest, you'll see the latter added CORS support. Your attempt at implementing CORS support via the filter actually looks correct. However, CORS uses HTTP OPTIONS requests which are not dispatched by spring unless configured to do so (and you'll need a handler.) (continued in next comment...) – allenru Nov 29 '15 at 17:26
  • See http://stackoverflow.com/questions/26500954/sockjs-not-passing-credential-information-when-on-a-different-domaincors for a related discussion on the pre-flight options request. Also, take a look at the CorsPreflightController at line 186 of this class for an example handler if you choose to roll your own: https://github.com/Russell-Allen/CrossOrigin/blob/master/src/main/com/allenru/crossorigin/CrossOriginHandlerMapping.java – allenru Nov 29 '15 at 17:29
  • I am pretty sure this stack overflow link would assist you : http://stackoverflow.com/questions/32874421/websocket-in-spring-boot-app-getting-403-forbidden. So either you allow all by * or you update to latest spring boot version which has support for the same. – Ashwini Rao Nov 29 '15 at 19:59

3 Answers3

16

in your WebsocketConfig.java

@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
    stompEndpointRegistry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
}

notice:

.setAllowedOrigins("*")
carfield
  • 161
  • 1
  • 4
  • Something weird is happening in my case when i add this code ` stompEndpointRegistry.addEndpoint("/stomp").setAllowedOrigins("*").withSockJS()` any request to "/stomp" works but "/stomp/info" give 403, any idea ? – Dany Y Nov 29 '18 at 15:23
  • in your WebSecurityConfigurer, checks that your antMatcher is something like this : "/stomp/**" and not only "/stomp" to allow any URL starting with /stomp and not only the "/stomp" URL – Y.M. Oct 01 '19 at 11:17
2

Something I just found and I thought it might help someone. Your url must NOT have a "/" at the end.

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/chat")
            .setAllowedOrigins("https://somewebsite.com/")
            .withSockJS();
}

Doesn't work.

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/chat")
            .setAllowedOrigins("https://somewebsite.com")
            .withSockJS();
}

Works.

Sebastian
  • 21
  • 1
2

It's .setAllowedOriginPatterns("*") instead of .setAllowedOrigins("*") in Spring 5+ versions.. (I don't know when it was changed)