有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用Zuul中的CORS作为API网关+AngularJS+微服务

我有一个应用程序使用Zuul Netflix作为API网关,其架构如下:

enter image description here

该体系结构运行良好,使用浏览器和postman,我可以从微服务(服务1、2和3)访问不同的REST端点。但当我试图在我的前端web应用程序(AngularJS WebApp)中使用它时,它在chrome控制台中给了我以下错误

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

如果我设置@CrossOrigin注释,那么通过自己的地址和端口使用服务将有效。但是当通过网关访问它时,rest端点上的no@CrossOrigin注释将不起作用

试图在我的安全配置中创建下面的过滤器,但仍然不起作用,而是在chrome控制台中出现下面的错误

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

浏览器控制台(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.

下面是AngularJS HTTP请求的示例

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

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

有人知道怎么处理吗?这里和那里有很多教程,但他们的webapp也是一个spring boot应用程序,要么位于api gateway中,要么与@EnableZuulProxy注释分离,这不是我想要的

如果有人能帮忙,请提前谢谢


共 (4) 个答案

  1. # 1 楼答案

    你能试试下面的代码吗。很好用

    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() {
        }
    
    }
    
  2. # 2 楼答案

    使用类似的架构,面对类似的问题,我做了以下改变并为我工作:

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

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

    在我的http请求中,我添加了标题

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

    为我工作

    我试图在最初的情况下,我只能访问Zuul路由映射中映射的第一个URL。但是在将/**替换为*之后,可以毫无问题地访问所有映射,角度方面也是如此,所有请求都应该包括头。 我对这个问题也很陌生,可能以后我会有更多的信息和细节,现在我可以说它对我有用,希望它也对你有用

  3. # 3 楼答案

    如果您正在部署Azure应用程序服务,可以在左侧菜单中检查CORS配置

  4. # 4 楼答案

    我尝试了以下两种解决方案,只是想看看CORS头(“Access Control Allow-*”)是否添加到服务器响应中,仅供参考:

    测试1:config spring security

    配置spring web mvc配置程序:
    https://spring.io/blog/2015/06/08/cors-support-in-spring-framework
    并在Spring安全级别启用CORS:
    https://docs.spring.io/spring-security/site/docs/current/reference/html/web-app-security.html#cors

    结果:从http响应中看不到cors头

    测试2:将过滤器添加到:在返回响应时添加cors标题 https://stackoverflow.com/a/47485985/2893542

    结果:从http响应中看到cors头