4

我有一个使用spring云组件(eureka,zuul和auth服务器)的本地协调环境。这些组件都是作为单独的独立服务实现的。然后我有越来越多的组合UI /资源服务,其中各个服务都有自己的用户界面。 UI使用thymeleaf模板放在服务器端,但本质上是在浏览器中运行的angularjs单页面应用程序。春云Zuul和JWT刷新令牌

单个Zuul服务面向所有的ui /资源服务。我注释了所有UI /资源服务@EnableResourceServer并将@EnableOAuth2Sso添加到Zuul服务器。

在application.properties对于Zuul我有以下特性:

security.oauth2.client.accessTokenUri=http://localhost:8771/uaa/oauth/token 
security.oauth2.client.userAuthorizationUri=http://localhost:8771/uaa/oauth/authorize 
security.oauth2.client.clientId=waharoa 
security.oauth2.client.clientSecret=waharoa 
security.oauth2.client.preEstablishedRedirectUri=http://localhost:81/login 
security.oauth2.client.registeredRedirectUri=http://localhost:81/login 
security.oauth2.client.useCurrentUri=false 
security.oauth2.resource.jwt.keyValue=-----BEGIN PUBLIC KEY-----[ETC omitted]... 

这一切都似乎工作作为标榜。我的问题是当令牌到期时。

在Auth服务器中,我设置令牌在60秒内到期,刷新令牌在12小时内过期。当令牌过期时,zuul服务器无法获得新的令牌。

在这出现在日志中的zuul服务器:

BadCredentialsException:无法获得通过OAuth2TokenRelayFilter.getAccessToken

更新抛出有效的访问令牌: 我打开调试org.springframework.security。 OAuth的在zuul服务,得到了以下

17:12:33.279 DEBUG o.s.s.o.c.t.g.c.AuthorizationCodeAccessTokenProvider - Retrieving token from http://localhost:8771/uaa/oauth/token 
    17:12:33.289 DEBUG o.s.s.o.c.t.g.c.AuthorizationCodeAccessTokenProvider - Encoding and sending form: {grant_type=[refresh_token], refresh_token=[eyJhbGciOiJS[...deleted...]VgGRHGT8OJ2yDfNVvNA]} 
    17:12:37.279 WARN o.s.c.n.z.f.post.SendErrorFilter - Error during filtering 
[blah blah stacktrace many lines omitted] 
Caused by: org.springframework.security.authentication.BadCredentialsException: Cannot obtain valid access token 
     at org.springframework.cloud.security.oauth2.proxy.OAuth2TokenRelayFilter.getAccessToken(OAuth2TokenRelayFilter.java:99) 
     at org.springframework.cloud.security.oauth2.proxy.OAuth2TokenRelayFilter.run(OAuth2TokenRelayFilter.java:79) 
     at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112) 
     at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:193) 
     ... 106 common frames omitted 

在验证(UAA)服务端我可以看到zuul客户端(waharoa)一uthenticate,得到正确的用户的详细信息,然后打印:

17:12:37.288 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed 

我相信这意味着,auth服务器已经做了什么,它需要和作出答复的?它看起来像Zuul服务上没有正确设置,有什么建议吗?

有人请告知我需要在这里发布什么其他信息来找出令牌刷新不起作用的原因。我是一个春天的云noob和这个公约黑魔法是不是很清楚(我已经搜索和搜索的例子,我认为是一个常见的用例,但什么都没有发现)。

注2:我已经有以下豆在Zuul侧

@Bean 
    public OAuth2RestTemplate oauth2RestTemplate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) { 
     return new OAuth2RestTemplate(resource, context); 
    } 

继@AlexK意见,我还增加了以下的UserDetailsS​​ervice豆在验证方面

@Bean 
    @Override 
    public UserDetailsService userDetailsServiceBean() throws Exception { 
     return super.userDetailsServiceBean(); 
    } 

,并补充说到我的auth服务器配置

@Autowired 
    private UserDetailsService userDetailsService; 

@Override 
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 
     endpoints.tokenStore(tokenStore()).tokenEnhancer(jwtTokenEnhancer()) 
       .authenticationManager(authenticationManager).userDetailsService(userDetailsService) 
      .reuseRefreshTokens(false); 
} 

但结果相同。 refresh_token发生,但是当响应进入Zuul过滤器时它似乎仍然死亡。

注3:

@AlexK实际上是当场上。我发现学到的是,当令牌刷新时,它不仅从令牌存储刷新,而且需要调用底层的UserDetailsS​​ervice来再次获取用户详细信息。当我从Active Directory获得详细信息时,这需要大量的试验和错误来解决,但现在正在按照广告方式工作。我的(缺失),简单的UserDetailsS​​ervice豆如图注2这是自动连接到配置:

@Bean(name = "ldapUserDetailsService") 
public UserDetailsService userDetailsService() { 
    FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch(searchBase, "(sAMAccountName={0})", 
      contextSource()); 
    LdapUserDetailsService result = new LdapUserDetailsService(userSearch); 
    result.setUserDetailsMapper(new InetOrgPersonContextMapper()); 
    return result; 
} 

回答

1

我认为所有必要的线索是this Q和A

简而言之:

  1. 有问题的线索 - 有必要实现你的Zuul /侧了UiApp OAuth2RestTemplate。由于它在Spring Boot reference据说它不是默认
  2. 另一部分是这个问题的答案中创建的 - 有必要做一定的修改对OAuth的服务器端

之后,你让你的access_token通过refresh_token自动刷新。

P.S. 但是,当你refresh_token令牌过期,你仍然可以得到相同的错误!为了处理它,你可以在你获得一个新的access_token的同时自动更新你的refresh_token。在AuthorizationServerEndpointsConfigurer配置在auth服务器代码中使用reuseRefreshTokens(假):

@Override 
public void configure(AuthorizationServerEndpointsConfigurer endpoints) 
     throws Exception { 
    endpoints 
     .authenticationManager(authenticationManager) 
     .userDetailsService(userDetailsService) 
     .reuseRefreshTokens(false); // <--that's the key to get new refresh_token at the same time as new access_token 
} 

更彻底的解释here

+0

谢谢您的答复。我已经在Zuul方面有OAuth2RestTemplate。我注意到auth中没有UserDetailsS​​ervice的INFO,所以我按照你的链接添加了这个信息。不幸的是我仍然得到相同的结果。刷新)令牌过程似乎正常工作,但Zuul过滤器仍然会抛出异常。我仍然不知道这是为什么。 – LukeM

+0

你现场点亮。我的UserDetailsS​​ervice出现问题。 – LukeM

+0

恭喜!也许未来的读者可能会对UserDetailsS​​ervice的问题有所了解。我也很感兴趣 – AlexK