这似乎是一个非常常见的问题,并且有一个简单的答案,但是实现记录的解决方案对我来说不起作用。
我有一个用于所有传入请求的 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 - 希望有人能发现我做错了什么。
最佳答案
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/