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 into same origin security policy errors. Using Java CORS filter, you may allow the webpage to make requests from other domains as well (known as cross domain requests).
Read More : Spring security CORS filter
1. How CORS Filter Work?
CORS capability works by adding some specific HTTP headers that tell the browser that downloaded webpage should be allowed to make web requests to given/all domains. Also, you can add information to instruct browser to allow only certain HTTP methods (GET/PUT/POST/DELETE etc) on those domain URLs.
You will read a term ‘preflight request‘ in rest of the post, so let’s understand it first.
Access-Control-Request-Method
and Access-Control-Request-Headers
, and the Origin
header.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.
Now let’s go through CORS related HTTP headers to understand more.
1.1. Response Headers
- Access-Control-Allow-Origin : specifies the authorized domains to make cross-domain request. Use “*” as value if there is 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.
1.2. 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 actual request.
- Access-Control-Request-Headers : used when issuing a preflight request to let the server know what HTTP headers will be used in actual request.
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. Drop me your questions in comments section.
Happy Learning !!
References:
CORS Specification
Pre-flight requests
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
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?
//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.
Hi Olga, could you tell me what you did?
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
Hi,
how can a simple log of the JSON object received and the JSON object returned be achieved?
Thanks!
Hi! Is it possible to modify this in order to only allow access to specific web services? THanks
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);
}
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");
The only solution on internet that really helped me. Thanks!!
since resp is instance of ServletResponse, can we chain that variable, instead of servletResponse?
hello,
i have servlet class should i insert the code in servlet class or i should create a new corsfilter class ?
Add new servlet. Remember the SRP principle. [Link]
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 ?
Thank you! It works perfectly! You saved my day.
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 🙂
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)
Hi. I put a breakpoint inside a code it seems that my app doesn’t see my CORSFilter file.
Check if its correctly registered in application.
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?
Perhaps you are using servlet 3. Use
@WebFilter
annotation. This is commented in above example.