这似乎是一个非常常见的问题,并且有一个简单的答案,但实施记录的解决方案并不适合我。
我有一个zuul代理/网关,用于所有传入的请求,然后将这些请求转发到不同的微服务。每个传入请求都在标头中设置了正确的承载令牌(这在前端设置和验证(来自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的请求时没有设置Authorization标头,但是我可以在直接调用时看到它设置。
@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:
我已经制作了一个快速示例应用程序,它也剥离了身份验证标题... https://github.com/peavers/zuul-oauth-passthrough - 希望有人能够发现我做错了什么。
答案 0 :(得分:2)
sensitiveHeaders是黑名单,默认不为空,所以 让Zuul发送所有标题(除了“忽略”标题) 必须明确地将其设置为空列表。如果你这是必要的 想要将cookie或授权标题传递给你的后端。
所以-•-•
反过来工作。它们可以防止将标头下放到您的后端。您应该将其从列表中删除,而不是将“授权”标题添加到列表中:
sensitiveHeaders
或者像这样(如果你因为某些原因需要将Cookie缩小到你的后端(我希望你不这样做)):
zuul:
sensitiveHeaders: Cookie,Set-Cookie