简体   繁体   中英

How to work with CORS in Zuul as API gateway + AngularJS + Microservices

I have an application which uses Zuul Netflix as API gateway, the architecture is below:

在此处输入图片说明

The architecture is working fine, using the the browser and postman I can access different REST endpoint from the microservices (Service 1, 2 and 3). But when I tried to use it in my front-end web application (AngularJS WebApp) it gives me the following error in chrome console.

XMLHttpRequest cannot load http://localhost:8080/person/api/all. Response for preflight is invalid (redirect)

Using the service through its own address and port will work if I will set @CrossOrigin annotation. But when accessing it through the gateway and no @CrossOrigin annotation on the rest endpoint will not work.

Tried to create below filter in my Security configuration, but still didn't work, instead getting the below error in chrome console.

@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);
    }

Browser console (Chrome)...

XMLHttpRequest cannot load http://localhost:8080/person/api/all. Redirect from 'http://localhost:80/person/api/all' to 'http://localhost:80' has been blocked by CORS policy: Request requires preflight, which is disallowed to follow cross-origin redirect.

Below is the sample AngularJS HTTP request.

app.controller('loginCtrl', [
    '$scope', '$http', function($scope, $http) {

      $http.get('http://localhost:8080/person/api/all').then(function(data) {
        return console.log(data.data);
      });
]); 

Does anybody know how to deal with it? A lot of tutorials here and there but their webapp is also a spring boot application either siting in api gateway or separate with @EnableZuulProxy annotation which is not what I want.

If anybody can help, thanks in advance.

using similar architecture, faced similar problem, I did following changes and worked for me:

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);

to

config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("*", config);

and in my angular http request I added header,

{'Access-Control-Allow-Origin':'*'}

worked for me.

I was trying to in the original situation I was only able to access first ever URL mapped in the Zuul route mapping. but after replacing /** with * able to access all mappings without problem, also same goes with Angular side, all the requests should include the header. I am also new to this issue, may be I'll have more information and details later, for now I can say it worked for me, hopefully it'll work for you too.

I tried below 2 solutions, just to see if the CORS headers ("Access-Control-Allow-*") are added to the server responses, FYI:

Test 1: config spring security

Configure spring web mvc configurer:
https://spring.io/blog/2015/06/08/cors-support-in-spring-framework
And enable CORS at Spring Security level:
https://docs.spring.io/spring-security/site/docs/current/reference/html/web-app-security.html#cors

Result: No cors headers seen from http response

Test 2: Add filter to: add cors headers on returning response https://stackoverflow.com/a/47485985/2893542

Result: cors headers seen from http response

can you try as following code. its working fine.

package com.gatway.configuration;

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 CROSFilter implements Filter {

    private final Logger logger = LoggerFactory.getLogger(CROSFilter.class);

    public CROSFilter() {
        logger.info("CROSFilter 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, HEAD, PATCH, PUT");
        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() {
    }

}

如果要部署到 Azure 应用服务,则可以在左侧菜单中检查 CORS 配置。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM