'No 'Access-Control-Allow-Origin' error with Spring RESTful hosted in Pivotal web services

I create a RESTful API with Spring boot and host it in Pivotal web services.

Let's say the url is https://abc.cfapps.io/students and the json result will be

[

       {"id":1,"name":"Michael","score":8.5},
       {"id":2,"name":"Naomi","score":5.6}
]

Then I write an Angular client to send a request to that url:

angular.module("app", []).controller("listController", function($scope, $http)
{
    var url = 'https://abc.cfapps.io/students';
    var httpRequest = new XMLHttpRequest();
    httpRequest.open('GET', url, true);
    httpRequest.setRequestHeader('Access-Control-Allow-Origin', '*');
    httpRequest.setRequestHeader('Content-Type', 'application/json');
    httpRequest.onerror = function (XMLHttpRequest, textStatus, errorThrown) {
        console.log('failed');
        console.log(JSON.stringify(XMLHttpRequest));
    };
    httpRequest.onload = function () {
        console.log('SUCCESS!');
    }
    httpRequest.send();        
});

My client run in localhost:52442 and in my Spring boot service I also allow CORS, too.

@RestController
@CrossOrigin(origins = "http://localhost:52442")
@RequestMapping(value="/students")
public class StudentService
{

    @RequestMapping(value="/",method = RequestMethod.GET)
    public ArrayList<Student> getListStudents()
    {
        // return list
    }

// other methods
}

But I keep getting this error:

XMLHttpRequest cannot load https://abc.cfapps.io/students.         
Response to preflight request doesn't pass access control check:     
No 'Access-Control-Allow-Origin' header is present on the requested resource.        
Origin 'http://localhost:52442' is therefore not allowed access. The response had HTTP status code 403.


Solution 1:[1]

If your using the java code at backend

We can try to configure it in this way by creating a class for it

   package com.web;

   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.
 */
@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() {}

}

I think this might be useful

Solution 2:[2]

Try the below format of $http GET call with header's set to allow cross origin

    $http({method: 'GET',
           url: 'https://abc.cfapps.io/students',
           cache:false,
           headers: {
                'Access-Control-Allow-Origin': '*',
                'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
                'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With',
                'X-Random-Shit':'123123123'
            }})
            .success(function(outputData) {
    });

Solution 3:[3]

import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class CORSFilter implements  Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        String origin = "";
        if(request.getHeader("origin") != null){
            origin = request.getHeader("origin");
            response.setHeader("Access-Control-Allow-Origin", origin);
        }
        if(origin.isEmpty()){
            response.setHeader("Access-Control-Allow-Origin", "*");
        }

        response.setHeader("Access-Control-Allow-Credentials", "true");
        //TRACE
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, PATCH, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
        chain.doFilter(req, res);
    }

    public void init(FilterConfig filterConfig) {}

    public void destroy() {}

}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.firewall.DefaultHttpFirewall;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.sql.DataSource;
import java.util.Arrays;

@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
            http.cors()
                .and()
                .requestMatchers()
                    .antMatchers("/version", "/login", "/oauth/authorize")
                .and()
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
                .formLogin().permitAll();
    }

    //.....
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sanket
Solution 2 ngCoder
Solution 3 Prince Foli