Spring Cloud Zuul API网关不会为无状态会话转发JWT令牌

时间:2017-09-07 13:23:35

标签: spring-boot spring-security-oauth2 netflix-zuul spring-cloud-netflix

我正在尝试使用移动/网络端点消耗的 Spring Boot 1.5.6.RELEASE Spring Cloud Dalston.SR3 来实现微服务架构后端。< / p>

API网关应用

@SpringBootApplicatio
@EnableEurekaClient
@EnableZuulProxy
public class GatewayApplication {

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

API安全性

@Configuration
@EnableWebSecurity
@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
@EnableOAuth2Sso
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {

        // @formatter:off
        http
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .authorizeRequests()
                    .antMatchers("/sign-up", "/login")
                        .permitAll()
                .anyRequest()
                    .authenticated()
            .and()
                .csrf()
                    .ignoringAntMatchers("/sign-up", "/login")
                    .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
        // @formatter:on
    }
}

Gradle安全相关的依赖项

   // Spring OAuth2 security
    compile("org.springframework.boot:spring-boot-starter-security")
    compile("org.springframework.security.oauth:spring-security-oauth2")
    compile("org.springframework.cloud:spring-cloud-starter-oauth2")
    compile("org.springframework.security:spring-security-jwt")

Zuul路线

zuul:
  ignoredServices: '*'
  routes:
    user-service:
      path: /user-service/**
      stripPrefix: false
      serviceId: user-webservice
      sensitiveHeaders:
    task-service:
      path: /task-service/**
      stripPrefix: false
      serviceId: task-webservice
      sensitiveHeaders:
    user:
      path: /userauth/**
      stripPrefix: false
      serviceId: auth-server
      sensitiveHeaders:

我可以从授权服务器获取访问令牌(无状态会话 - 没有JSESSIONID cookie)

  

curl -D - --request POST -u acme:acmesecret   &#34; http://localhost:8899/userauth/oauth/token?grant_type=password&username=&LT; ...&GT;&安培;密码= LT; ...&GT;&#34;

     

{&#34;&的access_token#34;:&#34; eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MDQ3ODg4NzgsInVzZXJfbmFtZSI6IjcyMTk2MTk2NDEiLCJhdXRob3JpdGllcyI6WyJST0xFX1BBVElFTlQiXSwianRpIjoiZThhMzBjNmQtZjA2MS00MWEzLWEyZGItYTZiN2ZjYTI5ODk1IiwiY2xpZW50X2lkIjoiYWNtZSIsInNjb3BlIjpbIm9wZW5pZCJdfQ.AhF_kqfsRYM1t1HVT ........

我可以使用访问令牌从授权服务器或其他资源请求数据

  

curl -D - --request GET -H&#34;授权:持票人   eyJhbGciOiJSUzI1 ....&#34; http://localhost:8899/userauth/me

     

{&#34;当局&#34;:[{&#34;权威&#34;:&#34; ROLE_P .........}

     

curl -D - --request GET -H&#34;授权:持票人   eyJhbGciOiJSUzI1NiIsInR5 .......&#34; http://localhost:8081/user-service/

     

[{&#34;的firstName&#34;:&#34;阿尼尔&#34; .....}]

但是,对于通过API网关路由的相同请求,它在网关本身失败并被过滤为AnonymousAuthenticationToken。

  

curl -D - --request GET -H&#34;授权:持票人   eyJhbGciOiJSUzI1 ....&#34; http://localhost:8765/user-service/

     

HTTP / 1.1 302 Set-Cookie:   XSRF-TOKEN = b5a1c34e-e83c-47EA-86a6-13a237c027d4;路径= /位置:   http://localhost:8765/login

我假设使用@EnableZuulProxy@EnableOAuth2Sso,Zuul会注意将承载令牌转发给下游服务,但这不会发生。我已经有一个使用HTTP会话和浏览器重定向的工作示例,以使API网关传递令牌 - https://github.com/anilallewar/microservices-basics-spring-boot

但是我很难让它与无状态会话一起工作,Zuul API网关端可能缺少什么指针?

2 个答案:

答案 0 :(得分:2)

Zuul默认将Authorization标头视为敏感标头,并不将其传递给下游请求。要覆盖它,您可以全局修改Zuul配置中的sensitiveHeaders(对于所有路由):

zuul:
  # exclude Authorization from sensitive headers
  sensitiveHeaders: Cookie,Set-Cookie
  ignoredServices: '*'

或者针对特定路线:

zuul:
  ignoredServices: '*'
  routes:
    user-service:
      path: /user-service/**
      stripPrefix: false
      serviceId: user-webservice
      # exclude Authorization from sensitive headers
      sensitiveHeaders: Cookie,Set-Cookie

要查找有关此问题的更多信息,请查看以下问题:

Authorization header not passed by ZuulProxy starting with Brixton.RC1

答案 1 :(得分:1)

  

我假设使用@EnableZuulProxy和@ EnableOAuth2Sso,Zuul会小心地将承载令牌转发给下游服务但是没有发生。

我假设了同样的事情,但在我的(痛苦)体验中,@ EnableOAuth2Sso使用SSO保护所有端点,甚至阻止带有承载令牌的请求到达下游服务。我不得不更改我的网关以禁用导致我的资源的路由上的身份验证,以便带有Bearer令牌的请求可以通过。

尝试将/user-service/**/task-service/**添加到您的permitAll()匹配器中:

@Override
public void configure(HttpSecurity http) throws Exception {

    // @formatter:off
    http
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
            .authorizeRequests()
                .antMatchers("/sign-up", "/login", "/task-service/**", "/user-service/**")
                    .permitAll()
            .anyRequest()
                .authenticated()
        .and()
            .csrf()
                .ignoringAntMatchers("/sign-up", "/login")
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    // @formatter:on
}