Enable CORS in Spring Boot - Vue - spring-boot

I am trying to enable api endpoints to make them reachable in my Vue application.
I have tried set
#Configuration
#EnableWebSecurity
class SecurityConfig {
companion object {
private const val REGISTRATION_PATH = "/auth/register"
private const val AUTHENTICATION_PATH = "/auth/login"
}
#Bean
fun configure(
http: HttpSecurity,
delegatingAuthenticationEntryPoint: DelegatingAuthenticationEntryPoint
): SecurityFilterChain {
http.cors()
http.sessionManagement().sessionCreationPolicy(STATELESS)
http.authorizeRequests()
.antMatchers(REGISTRATION_PATH, AUTHENTICATION_PATH).permitAll()
.anyRequest().authenticated()
http.exceptionHandling()
.authenticationEntryPoint(delegatingAuthenticationEntryPoint)
return http.build()
}
and in endpoints I tried CrossOrigins
#CrossOrigin(origins = ["*"])
#PostMapping("/auth/register")
#ResponseStatus(CREATED)
fun register(#RequestBody registrationRequest: RegistrationRequest) =
authApiService.registerUser(registrationRequest)
But nothing seems to work. I have tried a lot of options from the previous topics but I keep getting CORS in my vue app. What else could be done?

Try this approach. It helps me, but I wrote in java, I converted it to kotlin by intellij idea
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
class CorsFilter : Filter {
#kotlin.Throws(IOException::class, ServletException::class)
override fun doFilter(req: ServletRequest, res: ServletResponse,
chain: FilterChain) {
val response = res as HttpServletResponse
response.setHeader("Access-Control-Allow-Origin", "*")
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE, PATCH")
response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, cache-control, x-requested-with")
response.setHeader("Access-Control-Max-Age", "3600")
if ("OPTIONS".equals((req as HttpServletRequest).method, ignoreCase = true)) {
response.status = HttpServletResponse.SC_OK
} else {
chain.doFilter(req, res)
}
}
override fun destroy() {
//Not implemented
}
#kotlin.Throws(ServletException::class)
override fun init(config: FilterConfig?) {
//Not implemented
}
}

Related

Angular spirngboot-preflight

1.In Spring boot I am adding "spring-boot-starter-security" dependency in pom.xml file and getting an error in angular console saying preflight error, even though I am overriding the method
#Configuration
#EnableWebSecurity
public class SpringSecurityConfigurationBasicAuth extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"/*").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic();
}
}
From browser i can directly access my data's by using link http://localhost:8080/users/.. and giving user id and password which are set by me in application.properties file.
But by using same user id and password i am not able to get data's form restlet-client(Similar app like Postman for testing API's).
proxy.conf.js file
module.exports = { "/myapi": { "target": "localhost:8080", "secure": false, "changeOrigin": true, "pathRewrite": { "^/myapi": "" } }
HttpInterceptorBasicAuthService.ts
#Injectable({ providedIn: 'root' }) export class HttpInterceptorBasicAuthService implements HttpInterceptor { constructor() { } intercept(request: HttpRequest<any>, next: HttpHandler){ let username='MSD' let password ='dummy' let basicAuthHeaderString = 'Basic '+ username + ':' + password; request=request.clone({ setHeaders : { Authorization : basicAuthHeaderString } }) return next.handle(request); } }
Anyone knows why this error is happening,please do sort out .
What is Pre Flight?
This pre-flight request (RequestMethod.OPTIONS) is made by some browsers as a safety measure to ensure that the request being done is trusted by the server. Meaning the server understands that the method, origin and headers being sent on the request are safe to act upon.
option 1: WebConfig for CORS
You can create one WebConfig Class for CORS Origin Configuration so that we don't need to write #CrossOrigin at each and every controller.
WebConfig.java
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
#EnableWebMvc
public class WebConfig implements Filter,WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
System.out.println("WebConfig; "+request.getRequestURI());
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With,observe");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Expose-Headers", "Authorization");
response.addHeader("Access-Control-Expose-Headers", "USERID");
response.addHeader("Access-Control-Expose-Headers", "ROLE");
response.addHeader("Access-Control-Expose-Headers", "responseType");
response.addHeader("Access-Control-Expose-Headers", "observe");
System.out.println("Request Method: "+request.getMethod());
if (!(request.getMethod().equalsIgnoreCase("OPTIONS"))) {
try {
chain.doFilter(req, res);
} catch(Exception e) {
e.printStackTrace();
}
} else {
System.out.println("Pre-flight");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Access-Control-Expose-Headers"+"Authorization, content-type," +
"USERID"+"ROLE"+
"access-control-request-headers,access-control-request-method,accept,origin,authorization,x-requested-with,responseType,observe");
response.setStatus(HttpServletResponse.SC_OK);
}
}
}
option 2 application.properties
# ENDPOINTS CORS CONFIGURATION (CorsEndpointProperties)
management.endpoints.web.cors.allow-credentials= # Whether credentials are supported. When not set, credentials are not supported.
management.endpoints.web.cors.allowed-headers= # Comma-separated list of headers to allow in a request. '*' allows all headers.
management.endpoints.web.cors.allowed-methods= # Comma-separated list of methods to allow. '*' allows all methods. When not set, defaults to GET.
management.endpoints.web.cors.allowed-origins= # Comma-separated list of origins to allow. '*' allows all origins. When not set, CORS support is disabled.
management.endpoints.web.cors.exposed-headers= # Comma-separated list of headers to include in a response.
management.endpoints.web.cors.max-age=1800s # How long the response from a pre-flight request can be cached by clients. If a duration suffix is not specified, seconds will be used.
option 3 #CrossOrigin:
#CrossOrigin(origins = {"http://domain1.com"})

How to enable CORS for Error Response in Spring MVC?

I'm working on application where I use Spring MVC for the Back-end and Angular5 for the Front-end. I have been stuck with implementation of Auth2 security layer including Cross-Origin Resource Sharing. My CORS filter implementation looks like this:
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
#WebFilter("/*")
public class WebSecurityCorsFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) request).getMethod())) {
res.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(request, res);
}
}
#Override
public void destroy() {
}
}
I works almost properly, I'm able to obtain access_token and use it to get protected data from ResourcesServer:
{"access_token":"4fcef1f8-4306-4047-9d4d-1c3cf74ecc44","token_type":"bearer","refresh_token":"397016eb-dfb0-4944-a2e0-50c3bd07c250","expires_in":29,"scope":"read
write trust"}
Browser console screenshot
The problem starts when I try to handle the request using expired token. In such case I'm not able to catch the correct ErrorResponeCode by Angular. Instead of 401 i Angular HttpClient got "Unknown Error" with status:0.
It looks like the problem is with CORS policy where the ErrorResponse doesn't include neccessery headers like Access-Control-Allow-Origin (...)
Failed to load http://localhost:8030/api/xxxx: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8070' is therefore not allowed
access. The response had HTTP status code 401.
ErrorResponse Headers - Screenshot
I have searched for how to enable CORS for ErorrResponse (InvalidTokenException etc.) in Spring MVC . I tried with various approach: accessDeniedHandler and setExceptionTranslator but without success. I really made effort to find the solution myself but I'm a beginner in Spring. I am not sure if this is possible at all.
ANGULAR (UPDATE)
#hrdkisback, it's rather not angular issue, anyway this my code :
#Injectable()
export class HttpInterceptorService implements HttpInterceptor {
addToken(req: HttpRequest<any>, oauthService: AuthenticationService): HttpRequest<any> {
if(oauthService.isTokenExist()){
return req.clone({ setHeaders: { Authorization: 'Bearer ' + oauthService.getAccessToken() }})
}
return req;
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
let oauthService = this.inj.get(AuthenticationService);
return next.handle(this.addToken(req,oauthService))
.do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// process successful responses here
}
}, (error: any) => {
if (error instanceof HttpErrorResponse) {
// Error
console.log(error);
}
});
}
}
Issue solved after I added my CORS filter on ResourcesServer configuration level like this:
The correct configuration that works for me!
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(new WebSecurityCorsFilter(), CsrfFilter.class)
...
}
....
}
In my previous configuration I added the filter in the same way but on the top level of MVC Security Configuration and it was the root couse of my issue:
The previous configuration that caused my issue
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(new WebSecurityCorsFilter(), CsrfFilter.class)
...
}
....
}
I faced the same problem..I was trying Basic Auth with Angular 5.
The problem is that you don't add the CORS header on error response.
Here is what I did
#Component
public class AuthEntryPoint extends BasicAuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
throws IOException, ServletException {
response.addHeader("WWW-Authenticate", "Basic realm=" +getRealmName());
response.addHeader("Access-Control-Allow-Origin", "http://localhost:4200");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter writer = response.getWriter();
writer.println("HTTP Status 401 - " + authEx.getMessage());
}
}
That would do the trick!

How do I enable CORS headers in the Swagger /v2/api-docs offered by Springfox Swagger?

I have the following file in my project:
#Configuration
#Order(Ordered.LOWEST_PRECEDENCE)
public class SwaggerConfig {
#Bean
public Docket apiSwagger2Documentation() { .... }
}
And in the Application.java there is:
#SpringBootApplication
#ComponentScan(basePackages = { ... })
#EnableSwagger2
public class Application {
...
}
The Swagger JSON is available under /v2/api-docs, that works fine.
What I would like to do, is to enable CORS headers for that endpoint.
For my own controllers, I have added #CrossOrigin to the controller classes, those APIs then have CORS headers, that works fine. But for the Swagger JSON URL I haven't written a controller myself, so I cannot use that annotation.
I have added the following method to the SwaggerConfig, as described in "Global CORS Configuration" in CORS support in Spring Framework.
#Bean
public WebMvcConfigurer corsConfigurer() {
System.out.println("*** corsConfigurer called");
return new WebMvcConfigurerAdapter() {
#Override public void addCorsMappings(CorsRegistry registry) {
System.out.println("*** addCorsMappings called");
registry.addMapping("/v2/api-docs");
}
};
}
Both print statements get printed, so the method is being called. But when I call the URL with curl:
curl -H "Origin: foo.com" \
-H "Access-Control-Request-Method: GET" \
-X OPTIONS \
--verbose \
http://localhost:9274/v2/api-docs
The CORS headers are not in the response. (In contrast to my own controller methods, annotated with #CrossOrigin, where the response does have the CORS headers.)
I am using springfox-swagger2 version 2.7.0, and spring-boot-starter-web 1.5.2.
What can I do to enable CORS headers on the Swagger JSON API endpoint?
I think you need a generic web filter as opposed to Web Mvc configuration.
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// Allow anyone and anything access. Probably ok for Swagger spec
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/v2/api-docs", config);
return new CorsFilter(source);
}
Thanks to #Barath for the answer. The solution was to ignore the Spring documentation, that code just seems to silently not work.
(It's a shame, the Spring stuff is quite advanced when it does work, for example, the "Access-Control-Allow-Headers" response header to the pre-flight request is set based on what headers the Java API method actually offers.)
Ignore Spring's implementation of CORS and do your own. I have put the code here that worked for me:
#Component
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", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "Foo, Bar, Baz");
chain.doFilter(req, res);
}
#Override
public void init(FilterConfig filterConfig) {}
#Override
public void destroy() {}
}
Remember to add any #RequestHeader that you've used in any REST method to the Access-Control-Allow-Headers response header

Spring security, cors error when enable Oauth2

I'm getting an error while querying my oauth/token endpoint.
I've configured cors enable for my resource / also tried to allow all resources but nothing worked.
XMLHttpRequest cannot load http://localhost:8080/oauth/token. 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:1111' is therefore not allowed
access. The response had HTTP status code 401.
vendor.js:1837 ERROR SyntaxError: Unexpected token u in JSON at position 0
at JSON.parse (<anonymous>)
at CatchSubscriber.selector (app.js:7000)
at CatchSubscriber.error (vendor.js:36672)
at MapSubscriber.Subscriber._error (vendor.js:282)
at MapSubscriber.Subscriber.error (vendor.js:256)
at XMLHttpRequest.onError (vendor.js:25571)
at ZoneDelegate.invokeTask (polyfills.js:15307)
at Object.onInvokeTask (vendor.js:4893)
at ZoneDelegate.invokeTask (polyfills.js:15306)
at Zone.runTask (polyfills.js:15074)
defaultErrorLogger # vendor.js:1837
ErrorHandler.handleError # vendor.js:1897
next # vendor.js:5531
schedulerFn # vendor.js:4604
SafeSubscriber.__tryOrUnsub # vendor.js:392
SafeSubscriber.next # vendor.js:339
Subscriber._next # vendor.js:279
Subscriber.next # vendor.js:243
Subject.next # vendor.js:14989
EventEmitter.emit # vendor.js:4590
NgZone.triggerError # vendor.js:4962
onHandleError # vendor.js:4923
ZoneDelegate.handleError # polyfills.js:15278
Zone.runTask # polyfills.js:15077
ZoneTask.invoke # polyfills.js:15369
With Postman everything works perfect.
My cors security configuration:
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedHeaders("*")
.allowedMethods("*")
.allowCredentials(true);
}
}
also tried to add http://localhost:1111 in allowed origins
Code in Postman:
require 'uri'
require 'net/http'
url = URI("http://localhost:8080/oauth/token")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/x-www-form-urlencoded'
request["authorization"] = 'Basic Y2hhdHRpbzpzZWNyZXRzZWNyZXQ='
request["cache-control"] = 'no-cache'
request["postman-token"] = 'daf213da-e231-a074-02dc-795a149a3bb2'
request.body = "grant_type=password&username=yevhen%40gmail.com&password=qwerty"
response = http.request(request)
puts response.read_body
After a lot of struggling i've overrided method configure(WebSecurity web) of class WebSecurityConfigurerAdapter because Authorization server configures this by itself and i just haven't found another solution. Also you need to permitAll "/oauth/token" Http.Options method. My method:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/oauth/token");
}
After this we need to add cors filter to set Http status to OK. And we can now intecept Http.Options method.
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
#WebFilter("/*")
public class CorsFilter implements Filter {
public CorsFilter() {
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");
response.setHeader("Access-Control-Max-Age", "3600");
if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig config) throws ServletException {
}
}
I found a way to fix the 401 error on Spring Security 5 and Spring Security OAuth 2.3.5 without turning off security for all OPTIONS requests on the token endpoint.
I realized that you can add a security filter to the token endpoint via the AuthorizationServerSecurityConfigurer. I tried adding a CorsFilter and it worked. The only problem I have with this method is I couldn't leverage Spring MVC's CorsRegistry. If anyone can figure out how to use the CorsRegistry, let me know.
I've copied a sample configuration for my solution below:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
#Configuration
#EnableAuthorizationServer
public static class AuthServerConfiguration extends AuthorizationServerConfigurerAdapter {
//... other config
#Override
public void configure(AuthorizationServerSecurityConfigurer security) {
//... other config
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.applyPermitDefaultValues();
// Maybe there's a way to use config from AuthorizationServerEndpointsConfigurer endpoints?
source.registerCorsConfiguration("/oauth/token", config);
CorsFilter filter = new CorsFilter(source);
security.addTokenEndpointAuthenticationFilter(filter);
}
}
This worked for me
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception
{
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.applyPermitDefaultValues();
// add allow-origin to the headers
config.addAllowedHeader("access-control-allow-origin");
source.registerCorsConfiguration("/oauth/token", config);
CorsFilter filter = new CorsFilter(source);
security.addTokenEndpointAuthenticationFilter(filter);
}
}
You could extend the AuthorizationServerSecurityConfiguration and override the void configure(HttpSecurity http) method to implement a custom cors configuration while leaving the rest untouched.
Here's an example:
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerSecurityConfiguration;
import org.springframework.web.cors.CorsConfiguration;
public class MyAuthorizationServerSecurityConfiguration extends AuthorizationServerSecurityConfiguration {
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.cors(httpSecurityCorsConfigurer -> httpSecurityCorsConfigurer.configurationSource(request -> {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedMethod("POST");
configuration.addAllowedHeader("Content-Type");
return configuration;
}));
}
}
And then, instead of using the default annotation #EnableAuthorizationServer which pulls in the default configuration class you can import the relevant classes on your own:
#Import({AuthorizationServerEndpointsConfiguration.class, MyAuthorizationServerSecurityConfiguration.class})
No need to alter any security configuration related to OPTIONS method and/or specific oauth paths.
I had CORS errors using XMLHttpRequest to send POST /logout requests (Keycloak and Spring Cloud OidcClientInitiatedServerLogoutSuccessHandler), so I used HTML form instead:
<form action="/logout" method="post">
<button>Logout</button>
</form>
it works without any issues and no CORS config is needed.

CORS issue with Spring Boot

I have a Spring Boot application running on port 8443, and an angular2 based front end on port 8080. I need my front end to make requests to my Spring server, but I'm getting CORS errors left and right. I have added the #CrossOrigin annotation to my RestController method, and I have added a CORSFilter to my project, and mapped it on web.xml, but on Firefox 46.0a2 I still get this error on the console:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at https://localhost:8443/allEquips. (Reason: CORS
header 'Access-Control-Allow-Origin' missing).
The relevant part of my controller:
#CrossOrigin
#RequestMapping("/allequips")
List<String> allequips(Model model) {
List<String> codes = equipmentRepository.findAllEquipments();
return codes;
}
The CORSFilter:
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, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
The mapping on web.xml:
<filter>
<filter-name>cors</filter-name>
<filter-class>config.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
And I don't know if this is important, but the Angular2 code that's making the http request:
#Injectable()
export class EquipService {
equips: Array<Equip>;
constructor(public http: Http) {
console.log('Equip service created.', http);
}
getEquips() {
return this.http.get(WebServiceEndPoint+'allEquips')
.map((responseData) => {
return responseData.json();
}).map((equips: Array<any>) => {
let result: Array<Equip> = [];
if(equips) {
equips.forEach((equip) => {
result.push(new Equip(equip.code));
});
}
return result;
}).subscribe( res => this.equips = res);
}
}
Am I missing some configuration? Is my code wrong in any way?
EDIT: I gave up and restarted from a previous commit. After that, simply adding #Cross-Origin was enough.
First Approach:-
If you are using spring boot then create a new class that extends WebMvcConfigurerAdapter
#Configuration
#ComponentScan
#EnableWebMvc
public class ApplicationConfig extends WebMvcConfigurerAdapter {
#Override
public void addCorsMappings(CorsRegistry registry) {
// Can just allow `methods` that you need.
registry.addMapping("/**").allowedMethods("PUT", "GET", "DELETE", "OPTIONS", "PATCH", "POST");
}
}
Second Approach:-
Also you can add this in the #SpringBootApplication annotated class. No xml needed.
origin, headers, methods etc are all configurable based on your needs.
#Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*"); // this allows all origin
config.addAllowedHeader("*"); // this allows all headers
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);
}
I'm pretty sure you need to add Content-Type in the allowed headers
response.setHeader("Access-Control-Allow-Headers", "x-requested-with x-uw-act-as");
Here's what I have working in my project:
#Component
public class CrossOriginRequestFilter implements Filter {
//Configurable origin for CORS - default: * (all)
#Value("${app.http.filter.cors.origin:*}")
private String originList;
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest)req;
HttpServletResponse httpResponse = (HttpServletResponse) res;
String origin = httpRequest.getHeader("Origin");
if (origin == null) {
//this is the case of mobile, where it sends null as Origin
httpResponse.setHeader("Access-Control-Allow-Origin", "*");
} else if (origin != null && originList.contains(origin)) {
httpResponse.setHeader("Access-Control-Allow-Origin", origin);
} else {
httpResponse.setHeader("Access-Control-Allow-Origin", "https://yourdomain.com");
}
httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
httpResponse.setHeader("Access-Control-Max-Age", "3600");
httpResponse.setHeader("Access-Control-Allow-Headers", "Accept, Accept-CH, Accept-Charset, Accept-Datetime, Accept-Encoding, Accept-Ext, Accept-Features, Accept-Language, Accept-Params, Accept-Ranges, Access-Control-Allow-Credentials, Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin, Access-Control-Expose-Headers, Access-Control-Max-Age, Access-Control-Request-Headers, Access-Control-Request-Method, Age, Allow, Alternates, Authentication-Info, Authorization, C-Ext, C-Man, C-Opt, C-PEP, C-PEP-Info, CONNECT, Cache-Control, Compliance, Connection, Content-Base, Content-Disposition, Content-Encoding, Content-ID, Content-Language, Content-Length, Content-Location, Content-MD5, Content-Range, Content-Script-Type, Content-Security-Policy, Content-Style-Type, Content-Transfer-Encoding, Content-Type, Content-Version, Cookie, Cost, DAV, DELETE, DNT, DPR, Date, Default-Style, Delta-Base, Depth, Derived-From, Destination, Differential-ID, Digest, ETag, Expect, Expires, Ext, From, GET, GetProfile, HEAD, HTTP-date, Host, IM, If, If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Keep-Alive, Label, Last-Event-ID, Last-Modified, Link, Location, Lock-Token, MIME-Version, Man, Max-Forwards, Media-Range, Message-ID, Meter, Negotiate, Non-Compliance, OPTION, OPTIONS, OWS, Opt, Optional, Ordering-Type, Origin, Overwrite, P3P, PEP, PICS-Label, POST, PUT, Pep-Info, Permanent, Position, Pragma, ProfileObject, Protocol, Protocol-Query, Protocol-Request, Proxy-Authenticate, Proxy-Authentication-Info, Proxy-Authorization, Proxy-Features, Proxy-Instruction, Public, RWS, Range, Referer, Refresh, Resolution-Hint, Resolver-Location, Retry-After, Safe, Sec-Websocket-Extensions, Sec-Websocket-Key, Sec-Websocket-Origin, Sec-Websocket-Protocol, Sec-Websocket-Version, Security-Scheme, Server, Set-Cookie, Set-Cookie2, SetProfile, SoapAction, Status, Status-URI, Strict-Transport-Security, SubOK, Subst, Surrogate-Capability, Surrogate-Control, TCN, TE, TRACE, Timeout, Title, Trailer, Transfer-Encoding, UA-Color, UA-Media, UA-Pixels, UA-Resolution, UA-Windowpixels, URI, Upgrade, User-Agent, Variant-Vary, Vary, Version, Via, Viewport-Width, WWW-Authenticate, Want-Digest, Warning, Width, X-Content-Duration, X-Content-Security-Policy, X-Content-Type-Options, X-CustomHeader, X-DNSPrefetch-Control, X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto, X-Frame-Options, X-Modified, X-OTHER, X-PING, X-PINGOTHER, X-Powered-By, X-Requested-With");
chain.doFilter(req, httpResponse);
}
#Override
public void destroy() {
}
}
Here originList is a list of origins you want to allow, configured from application.yml or properties file.

Resources