4

We are having a situation where UI is running on one host, and it is trying to communicate with the resources which are available on another host. The problem here is that, the UI is not be able to make call to the resources because that resource lives in a different domain and cross domain requests will not work unless the server is CORS enabled .

In-order to make server CORS enabled, We have done the below changes .

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

@Provider
public class CORSFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext request, ContainerResponseContext response) throws IOException
    {
        response.getHeaders().add("Access-Control-Allow-Origin", "*");
        response.getHeaders().add("Access-Control-Allow-Headers","origin, content-type, accept, authorization");
        response.getHeaders().add("Access-Control-Allow-Credentials", "true");
        response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
    }
}

However I am not able to figure out where I need to map/configure this class,since there is no config files (web.xml). I don't have much knowledge on enabling CORS on server-side . Please suggest how to proceed further .

6 Answers6

4

As far as I'm concerned the following are working

response.getHeaders().add("Access-Control-Allow-Origin", "*");
response.getHeaders().add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
response.getHeaders().add("Access-Control-Allow-Credentials", "true");
response.getHeaders().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS,HEAD");

Edit : (For spring cloud netflix and maybe others)

@Component
public class HeadersFilter implements Filter {
    @Override
    public void init(FilterConfig fc) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain fc) throws IOException, ServletException {
        if(servletResponse instanceof HttpServletResponse){
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            // here add the headers
        }
        fc.doFilter(servletRequest, servletResponse);
    }
    @Override
    public void destroy() {
    }
}
D. Peter
  • 487
  • 3
  • 12
  • Hi Peter, Thanks for the answer . Actually I have implemented the above snippet , but do I need to configure this to any config files – Soumyajit Chatterjee Jul 05 '17 at 04:06
  • Hi, as far as I'm concerned I'm using spring cloud netflix so a add the @Component annotation on a class that implements javax.servlet.Filter, I'll edit my post. But the configuration to add the filter depends on your web server – D. Peter Jul 05 '17 at 04:35
2

For a JavaEE 7 App you need to register this class in the ResourceConfig by adding following class to your war.

@ApplicationPath( "/" )
public class ApplicationConfig
    extends ResourceConfig {

   public ApplicationConfig() {
       register( new CORSFilter() );
   }

}

Maybe you also need to increase the priority of your Filter by adding the following class level annotation:

@Provider
@Priority( Priorities.HEADER_DECORATOR)
public class CORSFilter implements ContainerResponseFilter {
...
}
mszalbach
  • 10,612
  • 1
  • 41
  • 53
  • How can I register it to my ResourseConfig? – Bat Apr 06 '18 at 07:13
  • @Bat by creating a class extending from ResourceConfig like descriped in the first code block. JavaEE should find this class and apply the config from it. – mszalbach Apr 06 '18 at 08:57
1

In Jersey, I use the ResourceConfig class to register the CORSFilter. Like ,

import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;

public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        register(CORSFilter.class);
    }
}

`

and link this in web.xml like,

<init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.service.JerseyApplication</param-value>
        </init-param>  
Tanu
  • 24
  • 7
1

There are 2 things you have to do:

  1. If your resource is password protected, you have to allow preflight OPTIONS requests to run through without credentials, in web.xml e.g.:

    <security-constraint>
            <web-resource-collection>
            <web-resource-name>application</web-resource-name>
            <url-pattern>/*</url-pattern>
            <http-method-omission>OPTIONS</http-method-omission>
        </web-resource-collection>
        <auth-constraint>
            <role-name>user</role-name>
        </auth-constraint>
    </security-constraint>
    
  2. Use servlet filter to take care of preflight OPTIONS requests. For maven add this dependency

    <dependency>
        <groupId>com.thetransactioncompany</groupId>
        <artifactId>cors-filter</artifactId>
        <version>2.6</version>
    </dependency>
    

    add filter to web.xml:

    <filter>
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CORS</filter-name>
        <url-pattern>/rest/*</url-pattern>
    </filter-mapping>
    
kubo44
  • 63
  • 5
0

You have to enable it in your server first, check the website below to see how to configure your server (i.e., Tomcat) to enable CORS

https://enable-cors.org/server.html

fujy
  • 5,168
  • 5
  • 31
  • 50
0

I tested the codes above but the best one that was easy and fast to use was mentioned here: https://spring.io/blog/2015/06/08/cors-support-in-spring-framework I added @CrossOrgin to my API or controller calls whenever needed and worked perfectly.

Example Code:

@CrossOrigin
@GetMapping
public List<Product> getAllProducts(){return productService.getAllProducts();}

*You can also filter the access by adding your URL in front of @CrossOrigin

Hope you find this useful.

Hoomi
  • 61
  • 5