Java CORS Filter Example

Learn to use Java CORS filter. CORS is a mechanism that allows JavaScript on a web page to make AJAX requests to another domain.

Spring CORS Configuration

Cross-origin resource sharing (CORS) is a mechanism that allows JavaScript on a web page to make AJAX requests to another domain, different from the domain from where it originated. By default, such web requests are forbidden in browsers, and they will result in same-origin security policy errors. Using the Java CORS filter, you may allow the webpage to make requests from other domains as well (known as cross-domain requests).

Read More : CORS Filter using Spring Security

1. How does CORS Filter Work?

CORS capability works by adding some specific HTTP headers that tell the browser that the downloaded webpage should be allowed to make web requests to given/all domains. Also, we can add information to instruct the browser to allow only certain HTTP methods (GET/PUT/POST/DELETE etc) on those domain URLs.

1.1. Preflight Request

We will read the term ‘preflight request‘ in the rest of the post, so let’s understand it first.

A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood by another domain. It is an HTTP OPTIONS request using following HTTP request headers:

  • Access-Control-Request-Method
  • Access-Control-Request-Headers
  • Origin

A preflight request is automatically issued by a browser when needed; in normal cases, front-end developers don’t need to write such requests themselves. In response to a preflight request, the resource indicates which methods and headers it is willing to handle and whether it supports credentials.

1.2. HTTP Headers

Now let’s go through CORS-related HTTP headers to understand more.

Response Headers:

  • Access-Control-Allow-Origin: specifies the authorized domains to make cross-domain requests. Use “*” if there are no restrictions.
  • Access-Control-Allow-Credentials: specifies if cross-domain requests can have authorization credentials or not.
  • Access-Control-Expose-Headers: indicates which headers are safe to expose.
  • Access-Control-Max-Age: indicates how long the results of a preflight request can be cached.
  • Access-Control-Allow-Methods: indicates the methods allowed when accessing the resource.
  • Access-Control-Allow-Headers: indicates which header field names can be used during the actual request.

Request Headers

  • Origin: indicates where the cross-origin actual request or preflight request originates from.
  • Access-Control-Request-Method: used when issuing a preflight request to let the server know what HTTP method will be used in the actual request.
  • Access-Control-Request-Headers: used when issuing a preflight request to let the server know what HTTP headers will be used in the actual requests.

2. Java CORS Filter Example

Now let’s a very basic implementation of CORS filter which can be added to any web application.

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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet Filter implementation class CORSFilter
 */
// Enable it for Servlet 3.x implementations
/* @ WebFilter(asyncSupported = true, urlPatterns = { "/*" }) */
public class CORSFilter implements Filter {

	/**
	 * Default constructor.
	 */
	public CORSFilter() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
			throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) servletRequest;
		System.out.println("CORSFilter HTTP Request: " + request.getMethod());

		// Authorize (allow) all domains to consume the content
		((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Origin", "*");
		((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Methods","GET, OPTIONS, HEAD, PUT, POST");

		HttpServletResponse resp = (HttpServletResponse) servletResponse;

		// For HTTP OPTIONS verb/method reply with ACCEPTED status code -- per CORS handshake
		if (request.getMethod().equals("OPTIONS")) {
			resp.setStatus(HttpServletResponse.SC_ACCEPTED);
			return;
		}

		// pass the request along the filter chain
		chain.doFilter(request, servletResponse);
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
	}

}

Now register this filter in web.xml.

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>com.howtodoinjava.examples.cors.CORSFilter</filter-class>
</filter>
 
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

That’s all regarding using CORS filters in java web applications.

Happy Learning !!

References:

CORS Specification
Pre-flight requests

Leave a Comment

  1. Hi , I am trying to make an ajax call to consume my rest API through web application. My web app is https and webservices is of http. I am getting below error,

    Access to XMLHttpRequest at ‘http://portal-dev.test.com/Services/crs/wa_ind/?user=test&domain=portal&token=N7qA2PyuPP‘ from origin ‘https://portal-dev.test.com‘ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

    I added the filer to my web application but its not working. Can you please help me ?

    -Venkatesh A

    Reply
  2. HI

    If already i have implemented with CORS filter in web.xml and i am trying to implement another filter like HMAC filter in class or web.xml will it work?

    Reply
  3. //resp.setStatus(HttpServletResponse.SC_ACCEPTED);
    to get this example to work I had to comment out this status, and use a default 200ok response instead. Preflight response with 202 ACCEPTED didn’t work for me.

    Reply
  4. I need to add my custom Filter as a library for existing web applications without code changes in that application, kind of plug and play.

    Extended myclass with OncePerRequestFilter and Overrided dofilterInternal with my changes, but failed to add this in existing application.

    it works if I add below code @Bean
    public RequestFilter getdeta(){ return new RequestFilter(); }

    Is that possible to achieve it without adding the above code?

    Thanks in Advance

    Reply
    • Spec suggests that “Rather than allowing a space-separated list of origins, it is either a single origin or the string “null”.

      I will suggest using something like this. I have not tested it but it should work.

      String $http_origin = new URL(httpServletRequest.getRequestURL().toString()).getHost();

      if($http_origin == "http://www.domain1.com"
      || $http_origin == "http://www.domain2.com"
      || $http_origin == "http://www.domain3.com")
      {
      ((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Origin", $http_origin);
      }

      Reply
      • This example won’t work at all unless the “front-end-server” is hosted on the same machine/IP as the “back-end-server”.
        If we are to be picky with our consumers then we’d need to check the “Origin” header, not the host of the URL
        In your example:
        String http_origin = httpServletRequest.getHeader("Origin");

        Reply
  5. Hi,
    Wouldn’t this code set CORS headers with every response ? Isn’t that redundant ? Shouldn’t we only return headers for an OPTIONS call ?

    Reply
  6. whoever made this post, you should know that many people save their time of work and can doing something other that they love just because of you, thanks :)

    Reply
  7. i have a webapp that runs on one domain and sets a ContentPane (using a HttpPaneEx from echopoint) with a URL using html and .js files on another domain. Although this filter executes, the URL with html and .js do not get the headers set. Is there a way to do this?
    ApplicationInstance.getActive().getDefaultWindow().setContent(myContentPane);

    ContentPane
    httpPaneEx.setURI(http://otherdomain)

    Reply
  8. Please, I can’t find any web.xml file. My project is built with Maven. However, I am seeing a logback.XML file, which starts with

    Can I place the filter config there?

    Reply

Leave a Comment

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.