避坑指南(一):Spring Security Oauth2中refresh_token刷新access_token異常


 

轉載請注明作者及出處:

作者:銀河架構師

原文鏈接:https://www.cnblogs.com/luas/p/12118694.html

​問題

Spring Security Oauth2中,當access_token即將過期時,需要調用/oauth/token,使用refresh_token刷新access_token,此時會存在一個坑:

即如果使用Spring Security框架默認生成的AuthenticationManager時,接口調用異常。

具體報錯信息為如下:

No AuthenticationProvider found for org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken

 分析

為了解決此問題,翻閱了一些源碼及資料,發現端倪在於tokenServices。

使用默認tokenServices

首先是AuthorizationServerEndpointsConfigurer中框架創建tokenServices的邏輯。

如果沒有指定tokenServices,則創建默認的tokenServices,即DefaultTokenServices:

具體創建默認的tokenServices邏輯:

注意,默認創建的tokenServices並沒有初始化authenticationManager,這里是重點,下面會用到。

其次,DefaultTokenServices中刷新access_token的邏輯。

關於user再次認證的部分邏輯如下:

如上所述,默認的tokenServices因為沒有設置authenticationManager,所以不會走此邏輯,也就不會再次對用戶進行認證。

tokenServices自定義

自定義tokenServices邏輯如下:

@Bean
public DefaultTokenServices defaultTokenServices() throws Exception {
    DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
    defaultTokenServices.setAuthenticationManager(this.authenticationManager);
    defaultTokenServices.setTokenStore(jdbcTokenStore());
    defaultTokenServices.setClientDetailsService(jdbcClientDetailsServiceBuilder());
    
    // access token有效期2個小時
    defaultTokenServices.setAccessTokenValiditySeconds(60 * 60 * 2);
    // refresh token有效期30天
    defaultTokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 30);
    // 支持使用refresh token刷新access token
    defaultTokenServices.setSupportRefreshToken(true);
    // 允許重復使用refresh token
    defaultTokenServices.setReuseRefreshToken(true);
    return defaultTokenServices;
}
 

由於設置了自定義的authenticationManager,且此時身份認證模式為password,所以滿足刷新access_token令牌時,針對用戶進行的二次認證條件文章開始處已說明,則會觸發二次用戶認證。

 

此時,若采用Spring Security框架默認的authenticationManager,則必然會爆出文章開頭處描述的問題。因為框架默認的authenticationManager只包含一個DaoAuthenticationProvider。

Spring Security Oauth2框架中,存在一個開發者實現好的能認證PreAuthenticatedAuthenticationToken的Provider:PreAuthenticatedAuthenticationProvider。

 但是,Spring Security框架並沒有在默認authenticationManager中初始化,所以,DefaultTokenServices在執行刷新方法時,在二次認證的地方便會報錯。

 知道了問題的根本,就容易解決,添加PreAuthenticatedAuthenticationProvider到authenticationManager中應該就可以完美解決了。

 關於如何authenticationManager配置,方法多種多樣,如覆蓋掉Spring Security框架默認邏輯,或者完全自定義,都可以。本文不再贅述,后續也會出文章,詳細闡述Spring Security如何配置,結合Spring Security Oauth2如何配置等等。

 下面附上PreAuthenticatedAuthenticationProvider定義邏輯:

private PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider() {
    PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider = new PreAuthenticatedAuthenticationProvider();
    preAuthenticatedAuthenticationProvider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper(userDetailsService));
    return preAuthenticatedAuthenticationProvider;
}

 不得不說,Spring Security框架確實非常復雜,設計真是巧奪天工,不得不佩服設計者和開發者,由衷的贊嘆!

 

正文完!

 

微信搜索【銀河架構師】,發現更多精彩內容。

技術資料領取方法:關注公眾號,回復微服務,領取微服務相關電子書;回復MK精講,領取MK精講系列電子書;回復JAVA 進階,領取JAVA進階知識相關電子書;回復JAVA面試,領取JAVA面試相關電子書,回復JAVA WEB領取JAVA WEB相關電子書。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM