Nikita Vlasenko
Nikita Vlasenko

Reputation: 4352

Enabling CORS Spring issue with Spring Security

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.

Upvotes: 0

Views: 3232

Answers (3)

sharath
sharath

Reputation: 225

   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);
    }

}

Upvotes: 0

Danail
Danail

Reputation: 2232

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>

Upvotes: 1

MGR
MGR

Reputation: 286

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)

Upvotes: 0

Related Questions