首页 文章

Spring Cloud Zuul和JWT刷新令牌

提问于
浏览
4

我有一个使用spring cloud组件(eureka,zuul和auth服务器)的本地协调环境 . 这些组件都作为单独的独立服务实现 . 然后我有越来越多的组合UI /资源服务,其中各个服务都有自己的UI . UI使用百万美元模板放在服务器端,但实际上是在浏览器中运行的angularjs单页应用程序 .

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

在Zuul的application.properties中,我有以下属性:

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抛出的有效访问令牌

Update: 我打开了Zuul服务中org.springframework.security.oauth的调试并得到了以下内容

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

在Auth(uaa)服务端,我可以看到zuul客户端(waharoa)进行身份验证,获取正确用户的详细信息,然后打印:

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

我认为这意味着auth服务器已经完成了它所需要的并回复了请求?看起来Zuul服务上的设置不正确,有什么建议吗?

有人可以告诉我在这里发布的其他信息,以解决为什么令牌刷新不起作用 . 我是一个 Spring 天的 Cloud 菜鸟,这个常规黑魔法对我来说不是很清楚(我搜索并搜索了我认为是常见用例的例子,但没有发现) .

Note2: 我已经在Zuul方面拥有以下bean

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

在@AlexK建议之后,我还在Auth端添加了以下UserDetailsService Bean

@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过滤器时它似乎仍然死亡 .

Note 3:

@AlexK实际上是现货 . 我所学到的是,当令牌被刷新时,它不仅仅是从令牌存储刷新,它需要调用底层的UserDetailsService来再次获取用户的详细信息 . 当我从Active Directory获取详细信息时,需要进行大量的试验和错误才能解决,但现在正如宣传的那样工作 . 我(缺少)简单的UserDetailsService bean已自动装入配置中,如 Note 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 回答

  • 2

    我认为所有必要的线索都在this Q和A中

    简而言之:

    • 有问题的线索 - 它's necessary to implement OAuth2RestTemplate on your Zuul/UIApp side. As it'在Spring Boot reference中表示默认情况下不会创建

    • 另一部分在答案中 - 有必要在OAuth服务器端进行某些修改

    之后,您将通过refresh_token自动刷新access_token .

    附:但是当你的refresh_token令牌过期时,你仍然可以得到同样的错误!要处理它,您可以在获得新的access_token时自动更新refresh_token . 在auth-server代码中的AuthorizationServerEndpointsConfigurer配置中使用reuseRefreshTokens(false):

    @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

相关问题