java - Spring Cloud承载头透传

标签 java spring spring-cloud netflix-zuul

这似乎是一个非常常见的问题,并且有一个简单的答案,但是实现记录的解决方案对我来说不起作用。

我有一个用于所有传入请求的 zuul 代理/网关,然后将这些请求转发到不同的微服务。每个传入请求在 header 中都设置了正确的承载 token (这是在前端(来自 okta)设置和验证的,并确认它在跳过 Zuul 并直接访问服务时有效),我只需要将其传递到微服务。

EdgeServiceApplication

@EnableHystrix
@EnableZuulProxy
@EnableEurekaClient
@EnableOAuth2Sso
@SpringBootApplication
public class EdgeServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(EdgeServiceApplication.class, args);
    }
}

Zuul application.yml

server:
  port: 8080

logging:
  level:
    root: INFO
    org.springframework.web: INFO
    org.springframework.security: INFO

zuul:
  sensitiveHeaders: Cookie,Set-Cookie,Authorization

在我的微服务上,

@EnableEurekaClient
@SpringBootApplication
@EnableResourceServer
public class InstanceServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(InstanceServiceApplication.class, args);
    }
}

当我尝试通过 Zuul 向微服务发送请求时,我收到 401 响应。

将以下 bean 添加到我的微服务时,我可以看到当请求来自 Zuul 时没有设置授权 header ,但是我可以在直接调用时看到它设置。

@Bean
public FilterRegistrationBean requestDumperFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    Filter requestDumperFilter = new RequestDumperFilter();
    registration.setFilter(requestDumperFilter);
    registration.addUrlPatterns("/*");
    return registration;
}

我是 Spring 新手,所以只是希望我错过了 .yml 文件中某个地方的一些明显的东西?

当前依赖项

buildscript {
ext {
    springBootVersion = '1.5.8.RELEASE'
}
repositories {
    mavenCentral()
}
dependencies {
    classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    classpath('io.spring.gradle:dependency-management-plugin:0.5.4.RELEASE')
}
}

dependencies {
    compile('org.springframework.cloud:spring-cloud-starter-eureka')
    compile('org.springframework.cloud:spring-cloud-starter-config')
    compile('org.springframework.cloud:spring-cloud-starter-zuul')
    compile('org.springframework.cloud:spring-cloud-starter-ribbon')

    compile('org.springframework.boot:spring-boot-starter')
    compile('org.springframework.boot:spring-boot-starter-web')

    compile('org.springframework.boot:spring-boot-starter-data-rest')
    compile("org.springframework.boot:spring-boot-starter-actuator")
    compile('org.springframework.boot:spring-boot-starter-websocket')

    compile('org.springframework.security.oauth:spring-security-oauth2:2.2.0.RELEASE')
    compile('org.springframework.cloud:spring-cloud-security:1.2.1.RELEASE')
} 

更新:

按照建议更改我的申请后,我在任何请求上仍然会遇到 401 错误。

2017-11-02 11:03:05.697 ERROR 7139 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 401 null] with root cause

org.springframework.web.client.HttpClientErrorException: 401 null
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:78) ~[spring-web-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700)

我开始认为其他地方出了问题。我有一个 SecurityConfig 类,看起来像(我知道对于生产来说不安全)

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().antMatcher("/**")
                .authorizeRequests()
                .anyRequest().permitAll();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(ImmutableList.of("*"));
        configuration.setAllowedMethods(ImmutableList.of("*"));
        configuration.setAllowedHeaders(ImmutableList.of("*"));
        configuration.setAllowCredentials(true);

        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        source.registerCorsConfiguration("/**", configuration);

        return source;
    }
}

我的微服务上唯一的安全配置是

@EnableEurekaClient
@SpringBootApplication
@EnableResourceServer
public class InstanceServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(InstanceServiceApplication.class, args);
    }

    @EnableGlobalMethodSecurity(prePostEnabled = true)
    protected static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration {
        @Override
        protected MethodSecurityExpressionHandler createExpressionHandler() {
            return new OAuth2MethodSecurityExpressionHandler();
        }
    }

    @Bean
    protected ResourceServerConfigurerAdapter resourceServerConfigurerAdapter() {
        return new ResourceServerConfigurerAdapter() {
            @Override
            public void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests()
                        .anyRequest().authenticated();
            }
        };
    }

    @Bean
    public FilterRegistrationBean requestDumperFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        Filter requestDumperFilter = new RequestDumperFilter();
        registration.setFilter(requestDumperFilter);
        registration.addUrlPatterns("/*");
        return registration;
    }
}

更新#2:

注销请求头,仍然没有授权

2017-11-02 11:25:24.133  INFO 7381 --- [nio-8080-exec-2] s.s.e.s.c.LoggingRequestInterceptor      : URI         : http://instance-service
2017-11-02 11:25:24.133  INFO 7381 --- [nio-8080-exec-2] s.s.e.s.c.LoggingRequestInterceptor      : Method      : GET
2017-11-02 11:25:24.133  INFO 7381 --- [nio-8080-exec-2] s.s.e.s.c.LoggingRequestInterceptor      : Headers     : {Accept=[text/plain, application/json, application/*+json, */*], Content-Length=[0]}
2017-11-02 11:25:24.133  INFO 7381 --- [nio-8080-exec-2] s.s.e.s.c.LoggingRequestInterceptor      : Request body: 

更新#3:

我制作了一个快速示例应用程序,它还删除了身份验证 header ... https://github.com/peavers/zuul-oauth-passthrough - 希望有人能发现我做错了什么。

最佳答案

来自official documentation :

The sensitiveHeaders are a blacklist and the default is not empty, so to make Zuul send all headers (except the "ignored" ones) you would have to explicitly set it to the empty list. This is necessary if you want to pass cookie or authorization headers to your back end.

因此,sensitiveHeaders 的工作方式正好相反。它们防止 header 下游到您的后端。您应该将其从列表中删除,而不是将其添加到列表中,如下所示:

zuul:
  sensitiveHeaders: Cookie,Set-Cookie

或者像这样(如果您出于某种原因需要将 Cookie 下游到您的后端(我希望您不需要)):

zuul:
  sensitiveHeaders:

关于java - Spring Cloud承载头透传,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47049537/

相关文章:

java - 没有 web.xml 的 JNDI 引用和查找资源

java - OneJar URL 有什么问题吗?

java - 使用 Java 反射更改私有(private)静态最终字段

java - Spring PersistanceContext、EntityManager 和使用数据库

java - 如何处理@Transactional中的提交和回滚?

reverse-proxy - Netflix Zuul 停止重定向/启用反向代理

dependencies - 什么是发布火车 Bom?

java - 我如何在 Spring-Cloud 中将 ConsulDiscoveryClient 与 Zuul 和 Sidecar 一起使用

java - 从 HttpServletRequest 读取多个文件

html - 如何使用 Spring MVC 制作带有复选框的下拉列表?