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