Azure B2C背后的Spring Cloud Zuul无法获取访问令牌

时间:2018-12-06 08:20:17

标签: spring-cloud spring-security-oauth2 azure-ad-b2c

我已经为此工作了几个月了。我想我真的很亲近。 我的目标:使用Zuul网关提供微服务。在Zuul网关上放置OAuth2过滤器以保护微服务。 OAuth2提供程序是Azure B2C。 我想我正在使用OIDC和JWT。我所有的Zuul和服务都在同一台机器上,不同的端口上运行。
附言我计划在必要时使用Spring Session或Redis在所有微服务之间共享会话。

当我向Zuul发送请求时,它是localhost:8762 / res / images。我被重定向到B2C登录页面。用我的用户名密码登录后。我被重定向回localhost:8762 / login。具有非常长的代码属性。我猜它是auth_code或JWT令牌。此外,还有一个属性state = IuvHq6。不知道那是什么。网页显示的状态为401,无法获取访问令牌。

网关
Zuul网关POM gist
春天的云Edgware.SR4
Spring Boot Starter Web 1.5.13
Spring Cloud Starter Eureka 1.4.5
春季云启动器zuul 1.4.5
春季安全性oauth2 2.0.15
春季安全jwt 1.0.9

Zuul网关Java配置

@SpringBootApplication
@EnableEurekaClient // It acts as a eureka client
@EnableZuulProxy // Enable Zuul
public class ZuulgatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulgatewayApplication.class, args);
    }

}

安全配置

@Configuration
@EnableOAuth2Sso
public class SsoSecurityConfig extends WebSecurityConfigurerAdapter {// OAuth2SsoConfigurerAdapter
                                                                        // {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().cors().disable().logout().and().antMatcher("/**").authorizeRequests()
                .antMatchers("/index.html", "/", "/login").permitAll().anyRequest().authenticated().and()
                .csrf().disable();
    }
}

应用程序设置gist

Eureka微服务
Eureka服务POM gist
Spring Boot Starter数据保持2.0.5
Spring Cloud Starter NetFlix Eureka客户端2.0.1
Spring Boot Starter Web 2.0.5
Spring Cloud Security 1.2.3
春季安全oauth2自动配置2.1.1

Eureka服务配置

@SpringBootApplication
@EnableEurekaClient
public class ClusterdemoApplication {

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

Res Server配置

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Bean("resourceServerRequestMatcher")
    public RequestMatcher resources() {
        return new AntPathRequestMatcher("/images/**");
    }

    @Override
    public void configure(final HttpSecurity http) throws Exception {
        http
            .requestMatcher(resources()).authorizeRequests()
            .anyRequest().authenticated();
    }
}

RESTful API

@RestController
@RequestMapping("/")
public class HomeController {
    @Autowired
    private Environment env;

    @RequestMapping("/")  //use with context-path
    // @RequestMapping("/images")
    public List<Image> getImages() {
        List<Image> images = Arrays.asList(
            new Image(1, "Treehouse of Horror V", "https://www.imdb.com/title/tt0096697/mediaviewer/rm3842005760"),
            new Image(2, "The Town", "https://www.imdb.com/title/tt0096697/mediaviewer/rm3698134272"),
            new Image(3, "The Last Traction Hero", "https://www.imdb.com/title/tt0096697/mediaviewer/rm1445594112"));
        return images;
    }
}

应用程序配置gist

Eureka服务器
Eureka服务器POM gist
Spring Boot Starter Web 2.0.5
Spring Cloud Starter Netflix Eureka服务器2.0.1

Eureka服务器配置

@SpringBootApplication
@EnableEurekaServer
public class ClusterdemoApplication {
  public static void main(String[] args) {
    SpringApplication.run(ClusterdemoApplication.class, args);
  }
}

应用yml

spring:
  application:
    name: eureka-server
server:
  port: 8761
eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false

测试流程:
1.发送请求到Zuul网关。获取http://localhost:8762/res/images
2.重定向到B2C登录屏幕
3.登录
预期结果:显示图像链接的json
测试结果:重定向到微服务http://localhost:8762/login,但无法获得访问令牌错误

完整的结果URL样本

http://localhost:8762/login?state=3kJ31R&code=eyJraWQiOiJjcGltY29yZV8wOTI1MjAxNSIsInZlciI6IjEuMCIsInppcCI6IkRlZmxhdGUiLCJzZXIiOiIxLjAifQ..5ofS501Kavlbcrtn.c0Wq9m7ZQVwewQD1a_cmnTz4UhvNA50kqGSsF6UOTYhUvMVBv5qsNmHLkqopxQKbNhKImqUDNLqA7t8qgEYIN59juuFCou0kUkDDFmNspSYCLCebhIEeu9EgkCcUH-cqeVom4LjIJyw9QdeHcz8c-89ryLOz1zD9ISS-xGhHHt1DHd8cwtfy-WiVFOaFsvt2L-kSU8iA_cGY4ikT9rf5NdnZ5DSJjvRfNCZnsuKn6dS21McV-M9W1q3Ndyna2Gzf6xldj1SYACb-TxGG-lcOJWnlyf-U2SzZOK_F-r41ZHwxT1cw2iyFHr8qrCaaNRWGJstQ4c2Bs9Vsx0eIi9t_7JXhr4OqfnwAL7vqxlX8pIpaSgAbpQpEa3O7Y0ScNUKXr9HvNpVx9w--ebhkfdjYdBo0QE3RwB3jbKl0u-QGwRqNNUzMO1-DGd_tLhPeX-yLEFMsRSQhQCaeaNT_ZRdmyf63NsGxaOxSEpf3Z0eKJCY0A5knTHmH2A.7BkuNnBwxVL237E6vqMeAw

zuul网关调试控制台的输出

2018-12-06 16:14:18.134 DEBUG 7856 --- [nio-8762-exec-1] o.s.security.web.FilterChainProxy        : /res/images at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2018-12-06 16:14:18.135 DEBUG 7856 --- [nio-8762-exec-1] o.s.security.web.FilterChainProxy        : /res/images at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2018-12-06 16:14:18.138 DEBUG 7856 --- [nio-8762-exec-1] o.s.security.web.FilterChainProxy        : /res/images at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2018-12-06 16:14:18.138 DEBUG 7856 --- [nio-8762-exec-1] o.s.security.web.FilterChainProxy        : /res/images at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2018-12-06 16:14:18.139 DEBUG 7856 --- [nio-8762-exec-1] o.s.security.web.FilterChainProxy        : /res/images at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2ClientAuthenticationProcessingFilter'
2018-12-06 16:14:18.139 DEBUG 7856 --- [nio-8762-exec-1] o.s.security.web.FilterChainProxy        : /res/images at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2018-12-06 16:14:18.139 DEBUG 7856 --- [nio-8762-exec-1] o.s.security.web.FilterChainProxy        : /res/images at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2018-12-06 16:14:18.140 DEBUG 7856 --- [nio-8762-exec-1] o.s.security.web.FilterChainProxy        : /res/images at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2018-12-06 16:14:18.141 DEBUG 7856 --- [nio-8762-exec-1] o.s.security.web.FilterChainProxy        : /res/images at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2018-12-06 16:14:18.142 DEBUG 7856 --- [nio-8762-exec-1] o.s.security.web.FilterChainProxy        : /res/images at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2018-12-06 16:14:18.142 DEBUG 7856 --- [nio-8762-exec-1] o.s.security.web.FilterChainProxy        : /res/images at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2018-12-06 16:14:18.169 DEBUG 7856 --- [nio-8762-exec-2] o.s.security.web.FilterChainProxy        : /login at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2018-12-06 16:14:18.169 DEBUG 7856 --- [nio-8762-exec-2] o.s.security.web.FilterChainProxy        : /login at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2018-12-06 16:14:18.169 DEBUG 7856 --- [nio-8762-exec-2] o.s.security.web.FilterChainProxy        : /login at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2018-12-06 16:14:18.169 DEBUG 7856 --- [nio-8762-exec-2] o.s.security.web.FilterChainProxy        : /login at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2018-12-06 16:14:18.169 DEBUG 7856 --- [nio-8762-exec-2] o.s.security.web.FilterChainProxy        : /login at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2ClientAuthenticationProcessingFilter'
2018-12-06 16:14:26.766 DEBUG 7856 --- [nio-8762-exec-3] o.s.security.web.FilterChainProxy        : /login?state=3kJ31R&code=eyJraWQiOiJjcGltY29yZV8wOTI1MjAxNSIsInZlciI6IjEuMCIsInppcCI6IkRlZmxhdGUiLCJzZXIiOiIxLjAifQ..5ofS501Kavlbcrtn.c0Wq9m7ZQVwewQD1a_cmnTz4UhvNA50kqGSsF6UOTYhUvMVBv5qsNmHLkqopxQKbNhKImqUDNLqA7t8qgEYIN59juuFCou0kUkDDFmNspSYCLCebhIEeu9EgkCcUH-cqeVom4LjIJyw9QdeHcz8c-89ryLOz1zD9ISS-xGhHHt1DHd8cwtfy-WiVFOaFsvt2L-kSU8iA_cGY4ikT9rf5NdnZ5DSJjvRfNCZnsuKn6dS21McV-M9W1q3Ndyna2Gzf6xldj1SYACb-TxGG-lcOJWnlyf-U2SzZOK_F-r41ZHwxT1cw2iyFHr8qrCaaNRWGJstQ4c2Bs9Vsx0eIi9t_7JXhr4OqfnwAL7vqxlX8pIpaSgAbpQpEa3O7Y0ScNUKXr9HvNpVx9w--ebhkfdjYdBo0QE3RwB3jbKl0u-QGwRqNNUzMO1-DGd_tLhPeX-yLEFMsRSQhQCaeaNT_ZRdmyf63NsGxaOxSEpf3Z0eKJCY0A5knTHmH2A.7BkuNnBwxVL237E6vqMeAw at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2018-12-06 16:14:26.767 DEBUG 7856 --- [nio-8762-exec-3] o.s.security.web.FilterChainProxy        : /login?state=3kJ31R&code=eyJraWQiOiJjcGltY29yZV8wOTI1MjAxNSIsInZlciI6IjEuMCIsInppcCI6IkRlZmxhdGUiLCJzZXIiOiIxLjAifQ..5ofS501Kavlbcrtn.c0Wq9m7ZQVwewQD1a_cmnTz4UhvNA50kqGSsF6UOTYhUvMVBv5qsNmHLkqopxQKbNhKImqUDNLqA7t8qgEYIN59juuFCou0kUkDDFmNspSYCLCebhIEeu9EgkCcUH-cqeVom4LjIJyw9QdeHcz8c-89ryLOz1zD9ISS-xGhHHt1DHd8cwtfy-WiVFOaFsvt2L-kSU8iA_cGY4ikT9rf5NdnZ5DSJjvRfNCZnsuKn6dS21McV-M9W1q3Ndyna2Gzf6xldj1SYACb-TxGG-lcOJWnlyf-U2SzZOK_F-r41ZHwxT1cw2iyFHr8qrCaaNRWGJstQ4c2Bs9Vsx0eIi9t_7JXhr4OqfnwAL7vqxlX8pIpaSgAbpQpEa3O7Y0ScNUKXr9HvNpVx9w--ebhkfdjYdBo0QE3RwB3jbKl0u-QGwRqNNUzMO1-DGd_tLhPeX-yLEFMsRSQhQCaeaNT_ZRdmyf63NsGxaOxSEpf3Z0eKJCY0A5knTHmH2A.7BkuNnBwxVL237E6vqMeAw at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2018-12-06 16:14:26.767 DEBUG 7856 --- [nio-8762-exec-3] o.s.security.web.FilterChainProxy        : /login?state=3kJ31R&code=eyJraWQiOiJjcGltY29yZV8wOTI1MjAxNSIsInZlciI6IjEuMCIsInppcCI6IkRlZmxhdGUiLCJzZXIiOiIxLjAifQ..5ofS501Kavlbcrtn.c0Wq9m7ZQVwewQD1a_cmnTz4UhvNA50kqGSsF6UOTYhUvMVBv5qsNmHLkqopxQKbNhKImqUDNLqA7t8qgEYIN59juuFCou0kUkDDFmNspSYCLCebhIEeu9EgkCcUH-cqeVom4LjIJyw9QdeHcz8c-89ryLOz1zD9ISS-xGhHHt1DHd8cwtfy-WiVFOaFsvt2L-kSU8iA_cGY4ikT9rf5NdnZ5DSJjvRfNCZnsuKn6dS21McV-M9W1q3Ndyna2Gzf6xldj1SYACb-TxGG-lcOJWnlyf-U2SzZOK_F-r41ZHwxT1cw2iyFHr8qrCaaNRWGJstQ4c2Bs9Vsx0eIi9t_7JXhr4OqfnwAL7vqxlX8pIpaSgAbpQpEa3O7Y0ScNUKXr9HvNpVx9w--ebhkfdjYdBo0QE3RwB3jbKl0u-QGwRqNNUzMO1-DGd_tLhPeX-yLEFMsRSQhQCaeaNT_ZRdmyf63NsGxaOxSEpf3Z0eKJCY0A5knTHmH2A.7BkuNnBwxVL237E6vqMeAw at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2018-12-06 16:14:26.767 DEBUG 7856 --- [nio-8762-exec-3] o.s.security.web.FilterChainProxy        : /login?state=3kJ31R&code=eyJraWQiOiJjcGltY29yZV8wOTI1MjAxNSIsInZlciI6IjEuMCIsInppcCI6IkRlZmxhdGUiLCJzZXIiOiIxLjAifQ..5ofS501Kavlbcrtn.c0Wq9m7ZQVwewQD1a_cmnTz4UhvNA50kqGSsF6UOTYhUvMVBv5qsNmHLkqopxQKbNhKImqUDNLqA7t8qgEYIN59juuFCou0kUkDDFmNspSYCLCebhIEeu9EgkCcUH-cqeVom4LjIJyw9QdeHcz8c-89ryLOz1zD9ISS-xGhHHt1DHd8cwtfy-WiVFOaFsvt2L-kSU8iA_cGY4ikT9rf5NdnZ5DSJjvRfNCZnsuKn6dS21McV-M9W1q3Ndyna2Gzf6xldj1SYACb-TxGG-lcOJWnlyf-U2SzZOK_F-r41ZHwxT1cw2iyFHr8qrCaaNRWGJstQ4c2Bs9Vsx0eIi9t_7JXhr4OqfnwAL7vqxlX8pIpaSgAbpQpEa3O7Y0ScNUKXr9HvNpVx9w--ebhkfdjYdBo0QE3RwB3jbKl0u-QGwRqNNUzMO1-DGd_tLhPeX-yLEFMsRSQhQCaeaNT_ZRdmyf63NsGxaOxSEpf3Z0eKJCY0A5knTHmH2A.7BkuNnBwxVL237E6vqMeAw at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2018-12-06 16:14:26.767 DEBUG 7856 --- [nio-8762-exec-3] o.s.security.web.FilterChainProxy        : /login?state=3kJ31R&code=eyJraWQiOiJjcGltY29yZV8wOTI1MjAxNSIsInZlciI6IjEuMCIsInppcCI6IkRlZmxhdGUiLCJzZXIiOiIxLjAifQ..5ofS501Kavlbcrtn.c0Wq9m7ZQVwewQD1a_cmnTz4UhvNA50kqGSsF6UOTYhUvMVBv5qsNmHLkqopxQKbNhKImqUDNLqA7t8qgEYIN59juuFCou0kUkDDFmNspSYCLCebhIEeu9EgkCcUH-cqeVom4LjIJyw9QdeHcz8c-89ryLOz1zD9ISS-xGhHHt1DHd8cwtfy-WiVFOaFsvt2L-kSU8iA_cGY4ikT9rf5NdnZ5DSJjvRfNCZnsuKn6dS21McV-M9W1q3Ndyna2Gzf6xldj1SYACb-TxGG-lcOJWnlyf-U2SzZOK_F-r41ZHwxT1cw2iyFHr8qrCaaNRWGJstQ4c2Bs9Vsx0eIi9t_7JXhr4OqfnwAL7vqxlX8pIpaSgAbpQpEa3O7Y0ScNUKXr9HvNpVx9w--ebhkfdjYdBo0QE3RwB3jbKl0u-QGwRqNNUzMO1-DGd_tLhPeX-yLEFMsRSQhQCaeaNT_ZRdmyf63NsGxaOxSEpf3Z0eKJCY0A5knTHmH2A.7BkuNnBwxVL237E6vqMeAw at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2ClientAuthenticationProcessingFilter'

微服务调试控制台上没有任何显示。
我猜,Zuul网关未正确处理令牌。因此,没有访问令牌中继到实际的资源服务器。那就是微服务。

该如何解决?我想念什么?

我已经尝试过上下文路径,同样的错误 stackoverflow link

更新1:
我发现我的.yml似乎不正确。如果我想使用jwk。我应该将preferred-token-info设置为true。 在我改变了这一点之后。它有一个 class not found异常

java.lang.ClassNotFoundException: org.springframework.security.oauth2.provider.token.TokenStore

但是,我可以在spring-security-oauth2中找到该类,2.0.12和2.3.4都有它。

更新2:
在尝试了许多弹簧靴和弹簧云的组合之后。最接近的是 Spring Boot 1.5.16.RELEASE + Spring cloud Edgware.SR5。但是这种结合给了我 java.lang.ClassNotFoundException: org.springframework.security.oauth2.provider.token.RemoteTokenServices 如果我尝试修复它,将spring-security-oauth2版本强制为2.0.15.RELEASE。它产生
java.lang.ClassNotFoundException: org.springframework.boot.context.properties.bind.Bindable

我终于在不知道原因的情况下设法使其运行。有效的POM effective POM

但是后来我决定使用SCG,spring 2.0.5和Finchley.SR1。使其与资源服务器更加一致。
Spring Cloud Gateway配置:

spring.cloud.gateway:
  routes:
  - id: test
    uri: lb://image-service
    predicates:
    - Path=/res/images/**

最终结果是网关正在使用带有身份验证代码的client_id,client_secret。向Azure B2C / token终结点发送请求,以尝试检索访问令牌。并为空

java.lang.IllegalStateException: Access token provider returned a null access token, which is illegal according to the contract.
    at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:223) ~[spring-security-oauth2-2.1.0.RELEASE.jar:na]
Access token provider returned a null access token, which is illegal according to the contract.

complete error log

还要对B2C yml进行一些修改

security:
  basic:
    enabled: false
  oauth2:
    sso:
      loginPath: /login
    client:
      clientId: 111ddde5-38af-4c31-a540-f204d64ccc5e
      clientSecret: [protected]
      access-token-uri: https://login.microsoftonline.com/te/umediax.onmicrosoft.com/b2c_1_signinup/oauth2/v2.0/token
      user-authorization-uri: https://login.microsoftonline.com/te/umediax.onmicrosoft.com/b2c_1_signinup/oauth2/v2.0/authorize
      scope: openid
      auto-approve-scopes: true
      authorizedGrantTypes: authorization_code
      clientAuthenticationScheme: form
    resource:    
      jwk:
        key-set-uri: https://login.microsoftonline.com/te/umediax.onmicrosoft.com/b2c_1_signinup/discovery/v2.0/keys
      prefer-token-info: true

我该如何调试?

0 个答案:

没有答案