Access-Control-Allow-Origin is missing - spring

I am using the Spring 4 as backend for my angular Application.When the angular app makes a request to the spring app then I am getting an error
Access to **XMLHttpRequest at 'http://localhost:8080/AdminController/allAdmins' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.**
I am using custom filter to validate each user request
Code for my Filter is:
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpResp = (HttpServletResponse) response;
// Ignoring the request URLs
if (Utils.ignoreURLs(IGNORE_URLS, httpReq.getRequestURI()) == true) {
filterChain.doFilter(request, response);
return;
}
// Fetching all the header params from request
HttpServletRequest httpRequest = (HttpServletRequest) httpReq;
Enumeration<String> headerNames = httpRequest.getHeaderNames();
String loggedUserId = null;
String authToken = null;
if (headerNames != null) {
while (headerNames.nextElement() != null && headerNames.hasMoreElements()) {
loggedUserId = httpRequest.getHeader(Constants.LOGGED_USER_ID);
authToken = httpRequest.getHeader(Constants.AUTH_TOKEN);
}
}
if (Utils.isBlank(loggedUserId) == true || Utils.isBlank(authToken) == true) {
httpResp.setContentType(MediaType.APPLICATION_JSON_VALUE);
mapper.writeValue(httpResp.getWriter(), getErrorDetailsMap());
return;
}
ApplicationContext appContext = AppContextConfig.getApplicationContext();
AccessManager accessManager = (AccessManager) appContext.getBean(AccessManager.class);
// I am validating authentication token here
if(accessManager.isValidToken(loggedUserId, authToken) == false) {
httpResp.setContentType(MediaType.APPLICATION_JSON_VALUE);
mapper.writeValue(httpResp.getWriter(), getErrorDetailsMap());
return;
}
filterChain.doFilter(request, response);
}

Just use a #CrossOrigin annotation over the controllers and define this bean in your SecurityConfig:
#Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setExposedHeaders(Arrays.asList("x-auth-token", "xsrf-token"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
edit
Or maybe the problem is missing headers, in which the following filter should be sufficient.
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
#Component
public class SimpleCORSFilter implements Filter {
private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);
public SimpleCORSFilter() {
log.info("SimpleCORSFilter init");
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
chain.doFilter(req, res);
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}

Related

Spring Boot CORS issue

I am trying to learn spring with this tutorial:
https://spring.io/guides/tutorials/react-and-spring-data-rest/
but I am doing frontend app as a separate app.
While making a call to: http://localhost:8080/api/employees
how to enable CORS globally ? thanks!
Tried in Application with:
#Bean
public WebMvcConfigurer configurer()
{
return new WebMvcConfigurer()
{
#Override
public void addCorsMappings(CorsRegistry registry)
{
registry.addMapping("/api/*").allowedOrigins("http://localhost:8000");
}
};
}
but it does not help
did some testing with custom #RestController like here:
https://spring.io/guides/gs/rest-service-cors/#global-cors-configuration
and calling http://localhost:8080/api/greeting from external frontend app works fine, only those rest endpoints CRUD auto generated via spring are not allowed CORS there..
How to avoid this issue ?
Try adding this to your main application class file:
#Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
Adding:
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Note this is a very simple CORS filter that is wide open.
* This would need to be locked down.
* Source: https://stackoverflow.com/questions/39565438/no-access-control-allow-origin-error-with-spring-restful-hosted-in-pivotal-web
*/
#Component
public class CORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
helped
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.maxAge(3600L)
.allowedHeaders("*")
.exposedHeaders("Authorization")
.allowCredentials(true);
}
}

CORS error while calling Spring Boot Rest API from Ajax

We are running Spring boot apps on ubuntu server. We are using Netflix Zuul as API Gateway and Eureka as Service Registry. And used Apache2 as webserver for DNS.
When I am calling the APIs from my local via jQuery Ajax, I am getting the following exception:
Access to XMLHttpRequest at 'https://*****.com/api/users' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
And I can see "Origin: null" under Request Headers
Ajax code:
$.ajax({
type: "GET",
dataType: "json",
crossDomain: true,
headers: {
'Accept':'application/json',
'Content-Type':'application/json',
'Access-Control-Allow-Origin': "*"
},
url: "https://*****.com/api/users",
success: function(data){
//alert(data);
console.log(data);
}
});
To fix CORS tried following ways:
Added required config in apache:
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header set Access-Control-Max-Age "1000"
Header set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"
Added CorsMappings in WebMvcConfigurerAdapter implementation class:
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
Added CorsFilter bean in Zuul proxy class (annotated with #EnableZuulProxy):
#Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
But still same error. Any thoughts to fix this issue ?
Thanks.
SOLUTION 1:
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {
/**
* CORS filter for http-request and response
*/
public CORSFilter() {
}
/**
* Do Filter on every http-request.
*/
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "access_token, authorization, content-type");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
/**
* Destroy method
*/
#Override
public void destroy() {
}
/**
* Initialize CORS filter
*/
#Override
public void init(FilterConfig arg0) throws ServletException {
}
}
SOLUTION 2:
#CrossOrigin
#GetMapping("/getAnyThing")
public ResponseEntity<Object> getAnyThing() {
return ResponseEntity.ok(service.getAnyThing());
}
This will resolve your endPoints
The below complete class worked for me like a charm
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "*");
// response.setHeader("Access-Control-Expose-Headers","yourCustomHeaderIfExist");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}

How to configure dispatcher to redirect to home page when session is null or timed out

I am using Spring Mvc 3.x version. I don't want to write a if check on every single page. Instead, i need the code that is supported in Spring internally
Filter is the best suit for this kind of use case. You can intercept every request and check if there is an active session
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class AuthenticationFilter implements Filter {
private ServletContext context;
public void init(FilterConfig fConfig) throws ServletException {
this.context = fConfig.getServletContext();
this.context.log("AuthenticationFilter initialized");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
HttpSession session = req.getSession(false);
if (session == null) { //checking whether the session exists
this.context.log("Unauthorized access request");
res.sendRedirect(req.getContextPath() + "/loginPage.html");
} else {
// pass the request along the filter chain
chain.doFilter(request, response);
}
}
public void destroy() {
//close any resources here
}
}
This example has been taken from https://medium.com/#kasunpdh/session-management-in-java-using-servlet-filters-and-cookies-7c536b40448f. Check the article for details.
Add a filter in web.xml like:
<filter>
<filter-name>SessionFilter</filter-name>
<filter-class>
com.java.util.SessionFilter
</filter-class>
<init-param>
<param-name>avoid-urls</param-name>
<param-value>/Page1.htm</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>*.htm</url-pattern>
</filter-mapping>
The Filter implementation could be like -
public class FilterTest implements Filter {
...
private ArrayList<String> urlList;
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String url = request.getServletPath();
boolean allowedRequest = false;
if (urlList.contains(url)) {
allowedRequest = true;
}
if (!allowedRequest) {
HttpSession session = request.getSession(false);
if (null == session) {
response.sendRedirect("startup.jsp");
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
}
public void init(FilterConfig config) throws ServletException {
String urls = config.getInitParameter("avoid-urls");
StringTokenizer token = new StringTokenizer(urls, ",");
urlList = new ArrayList<String>();
while (token.hasMoreTokens()) {
urlList.add(token.nextToken());
}
}

Spring Boot Security No 'Access-Control-Allow-Origin' header is present on the requested resource Error

I'm building a Spring Boot application with Spring Security. I have a delete functionality which is done through AJAX request using JavaScript's Fetch API. The functionality works correctly in Chrome and Firefox, however it causes problem in Opera. As I mentioned, 'No 'Access-Control-Allow-Origin' header is present on the requested resource' error is shown in the console.
I searched for it, it was because of CORS, browsers normally doesn't allow AJAX requests to different origins, however delete request is in the same domain and if it does work in Chrome/Firefox, I wonder why it doesn't in Opera.
Now, I'm not sharing any code related to application, just because if there was a problem in core, it wouldn't work in other browsers, would it? But in case any code should be shared, please say it, so I'll share. But right now, I don't even know what is wrong. Thanks beforehand.
You can allow your all header by implementing Filter.
Try with this:
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "*");
//response.setHeader("Access-Control-Expose-Headers","yourCustomHeaderIfExist");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}
And add #CrossOrigin annotation before your controller.
You can also try with add this bean:
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST","PUT", "DELETE");
}
};
}
Step 1: Removed all #CrossOrigin inside code
Step 2: Go to Application class and update it with following code
import java.util.Arrays;
import java.util.Collections;
import java.util.stream.Collectors;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
*
* #author vaquar
*
*/
#SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
#Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(Collections.singletonList("*"));
config.setAllowedHeaders(Collections.singletonList("*"));
config.setAllowedMethods(Arrays.stream(HttpMethod.values()).map(HttpMethod::name).collect(Collectors.toList()));
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

Spring CrossOrigin issue: No Access-Control-Allow-Origin Header is present on the requested resource returning 401 as HTTP response

I have an API which takes two header ACCESS_TOKEN and TIME_OF_CALL as well as input parameter as mentioned below.
#RequestMapping(value = "/pay/capture", method = RequestMethod.GET)
#ResponseBody
#CrossOrigin(allowedHeaders = "ACCESS_TOKEN,TIME_OF_CALL", origins = "*")
public ResponseEntity<?> fetchRazorPayDetails(#RequestParam("id") Long id)
{/***logics here*/}
hitting this API from local host is returning 401 saying
XMLHttpRequest cannot load http://soandsoURL , response to preflight doesn't pass access control. check No Access-Control-Allow-Origin Header is present on the requested resource. origin 'http://localhost:1234' is therefore not allowed access. The response had HTTP status code 401
even though i had clearly annotated with
#CrossOrigin(allowedHeaders = "ACCESS_TOKEN,TIME_OF_CALL", origins = "*")
to accept all origin and two of the mentioned header. Am I missing something?
or values to allowedHeaders can't be comma separated? Any help on this issue
will be appreciated.
You can add a custom filter as bellow :
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, x-requested-with, authorization");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}
Since the issue was with Options(unauthorised 401 was the error), PFA screenshot.
It was just because I was declaring/adding options with #CrossOrigin. earlier it was `
#RequestMapping(value = "/pay/capture", method = RequestMethod.GET)
#ResponseBody
#CrossOrigin(allowedHeaders = "ACCESS_TOKEN,TIME_OF_CALL", origins = "*")
public ResponseEntity<?> fetchRazorPayDetails(#RequestParam("id") Long id)
{/***logics here*/}`
I removed optional parameter from #CrossOrigin and simply kept as
#RequestMapping(value = "/pay/capture", method = RequestMethod.GET)
#ResponseBody
#CrossOrigin
public ResponseEntity<?> fetchRazorPayDetails(#RequestParam("id") Long id)
{/***logics here*/}
and it worked.
Do something like this in your custom filter class:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = this.getAsHttpRequest(req);
HttpServletResponse httpResponse=this.getAsHttpResponse(res);
httpResponse.setHeader("Access-Control-Allow-Origin", "*");
httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
httpResponse.setHeader("Access-Control-Max-Age", "3600");
httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, x-requested-with, authorization, ACCESS_TOKEN, TIME_OF_CALL");
chain.doFilter(req, res);
}
private HttpServletResponse getAsHttpResponse(ServletResponse response)
{
if (!(response instanceof HttpServletResponse)) {
throw new RuntimeException("Expecting an HTTP request");
}
return (HttpServletResponse) response;
}
private HttpServletRequest getAsHttpRequest(ServletRequest request)
{
if (!(request instanceof HttpServletRequest)) {
throw new RuntimeException("Expecting an HTTP request");
}
return (HttpServletRequest) request;
}
And In the WebSecurity class do like this. It will work
//To allow Pre-flight [OPTIONS] request from browser
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}

Resources