0

I need to enable CORS for Spring application that uses Spring Security and it is not working. I am making GET request from http://localhost:3000 (which is node.js server) to http://localhost:8080 (which is Tomcat server).

I tried the following approaches but can not make any of them work: https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

Spring Data Rest and Cors

https://gist.github.com/zeroows/80bbe076d15cb8a4f0ad

Enabling CORS using Spring Boot 1.3.3-RELEASE

Spring CORS controller annotation not working

Currently I have a @Controller:

@Controller
@RequestMapping("/views")
public class LoginController{

@Autowired
private EventService eventService;

@RequestMapping(value = "/companies", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
    public String listCompanies(Model model) {
        String companiesList = eventService.getCompanies();
        return companiesList;
    }
}

And AppConfig file where I have been unsuccessfully trying to allow CORS:

@EnableWebMvc 
@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {

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

I want to somehow get the json from the listCompanies method in my Angular2 app. I am getting No 'Access-Control-Allow-Origin' header is present error, so I suppose it is CORS issue.

Community
  • 1
  • 1
Nikita Vlasenko
  • 4,004
  • 7
  • 47
  • 87
  • Can you try adding allowedMethods("\*") like registry.addMapping("/**"). allowedMethods("\*"); – K. Siva Prasad Reddy Jun 29 '16 at 03:32
  • Giving the same error in browser. In Eclipse's console I see `Access is denied (user is anonymous)`. I have Spring Security login there, so probably it is trying to redirect me to login page. – Nikita Vlasenko Jun 29 '16 at 03:43
  • I just need a solution for local development, not for production, so if Spring Security is causing the issue, then to disallow it somehow might solve it, but I do not know how (and it should not be too many changes since it will make local development worse) – Nikita Vlasenko Jun 29 '16 at 03:44

3 Answers3

1

I had similar problem and fixed it with custom filter as described in documentation: 27.5 Filter based CORS support

Basically, you need to create filter:

public class MyCorsFilter extends CorsFilter {

    public MyCorsFilter() {
        super(configurationSource());
    }

    private static UrlBasedCorsConfigurationSource configurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*");
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        config.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }

}

and then add it in web.xml (or corresponding java based config) before springSecurityFilterChain like this:

<filter>
    <filter-name>corsFilter</filter-name>
    <filter-class>com.example.configuration.cors.MyCorsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>corsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

I also have dispatchOptionsRequest (which is not necessary according to the new documentation):

<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    ...
    <!-- "OPTIONS" method support -->
    <init-param>
        <param-name>dispatchOptionsRequest</param-name>
        <param-value>true</param-value>
    </init-param>
    ...
</servlet>
Danail
  • 1,997
  • 18
  • 21
0

Did you defined somewhere the allowed origines in spring configuration? http://localhost:8080

@EnableWebMvc 
@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
        .allowedOrigins("http://localhost:3000")
        .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
        .allowCredentials(true);
    }
}

Look at chapter 27.3 of official docs to enable global CORS configuration : http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html

If you don't need to include cookies on cross-origin request, replace .allowCredentials(true) by .allowCredentials(false)

MGR
  • 286
  • 3
  • 5
  • I edited my post. The origin must be localhost:3000 (your node server), not localhost:8080. Otherwise you can try with the * wilcard but it's not recommanded for production! – MGR Jul 01 '16 at 05:40
  • 1
    That's the issue: it seems like when we have Spring Security and want to enable CORS, smth weird is going on and regular ways of enabling it are not working because I tried virtually everything I could find on the Internet. Hours of trying this and that lead me nowhere. Maybe some things work for enabling CORS however Spring Security issues authentication issues and is trying to redirect me to login page. Still in that case I am seeing this CORS error on the front end, it is the same always, no matter what is the output in the console in Eclipse. – Nikita Vlasenko Jul 02 '16 at 07:25
0
   import java.io.IOException;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * Enabling CORS support  - Access-Control-Allow-Origin
 * 
 * 
 * <code>
    <!-- Add this to your web.xml to enable "CORS" -->
    <filter>
      <filter-name>cors</filter-name>
      <filter-class>com.elm.mb.rest.filters.CORSFilter</filter-class>
    </filter>

    <filter-mapping>
      <filter-name>cors</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
 * </code>
 */
public class CORSFilter extends OncePerRequestFilter {
    private static final Log LOG = LogFactory.getLog(CORSFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        response.addHeader("Access-Control-Allow-Origin", "*");

        if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
            LOG.trace("Sending Header....");
            // CORS "pre-flight" request
            response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
//          response.addHeader("Access-Control-Allow-Headers", "Authorization");
            response.addHeader("Access-Control-Allow-Headers", "Content-Type");
            response.addHeader("Access-Control-Max-Age", "1");
        }

        filterChain.doFilter(request, response);
    }

}
sharath
  • 215
  • 3
  • 4