1. 程式人生 > 其它 >Spring Security OAuth 2.x的重新整理token介面/oauth/token自定義修改

Spring Security OAuth 2.x的重新整理token介面/oauth/token自定義修改

參考資料:

在OAuth 2中模仿DefaultTokenServices寫一個新的tokenServices來提供個性化服務
https://my.oschina.net/u/3768341/blog/2998273

Spring Security OAuth 2.x的重新整理token方法自定義修改

使用maven依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>1.3.5.RELEASE</version>
</dependency> 
<dependency> 
    <groupId>org.springframework.security.oauth</groupId> 
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.0.9.RELEASE</version>
</dependency>

需求:

舊專案的其中一個前端頁面會頻繁呼叫token重新整理方法。

重新整理的token介面會返回一個新的token令牌值給前端,舊的token令牌作廢掉。

重新整理介面時Oauth2框架自帶的介面

/oauth/token?access_token=8192be8f-4564-42cc-9f0f-7049be5ee085&grant_type=refresh_token&refresh_token=4f9ad8f9-885c-4cab-9f39-dc18887b526a&scope=read

請求引數:

access_token: af917135-211e-4dc4-8403
-e436a414f7da grant_type: refresh_token refresh_token: 4c6f36e8-fb51-44d5-8f87-1ce7e55aa504 scope: read

返回資料:

access_token: "fcb856b1-c325-46cd-bad4-f5d423688a5d"
expires_in: 1799
refresh_token: "4c6f36e8-fb51-44d5-8f87-1ce7e55aa504"
scope: "read"
token_type: "bearer"

而前端頁面可以開啟新的視窗,這個新視窗也需要用到token訪問後端。

到這個新視窗也觸發到某一個前端頁面的重新整理token機制時,會呼叫token重新整理介面。

導致 新視窗的token值變更的,而舊視窗的token值沒有變

舊視窗再次攜帶舊token請求後端時因為token無效,重定向跳轉到的登入頁面。

解決方法:
方法1、呼叫重新整理token方法時,不進行token更新,返回原來的token內容。
可以避免兩個視窗的token不一樣導致跳轉到登入頁面。

本地調式程式碼後,發現重新整理token的最終方法是呼叫DefaultTokenServices類的重新整理token方法

OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest)

網上搜索資料,可以在配置時,自定義的tokenService代替預設實現類。

具體配置類,主要檢視第8行,配置endpoints

 1 @Configuration
 2 @EnableAuthorizationServer
 3 public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
 4 
 5     @Override
 6     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
 7         // 自定義tokenservice方法
 8         endpoints.tokenServices(tokenServices(endpoints));
 9         endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
10 //                .reuseRefreshTokens(false)
11                 .authenticationManager(authenticationManager).userDetailsService(defaultUsersDetailsService);
12     }
13         
14     private MyTokenService tokenServices(AuthorizationServerEndpointsConfigurer endpoints) {
15         MyTokenService tokenServices = new MyTokenService();
16         tokenServices.setTokenStore(tokenStore);
17         tokenServices.setSupportRefreshToken(true);//支援重新整理token
18         tokenServices.setReuseRefreshToken(true);
19         tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
20         tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
21         addUserDetailsService(tokenServices, defaultUsersDetailsService);
22         return tokenServices;
23     }
24 
25     private void addUserDetailsService(MyTokenService tokenServices, UserDetailsService userDetailsService) {
26         if (userDetailsService != null) {
27             PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
28             provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(
29                     userDetailsService));
30             tokenServices.setAuthenticationManager(new ProviderManager(Arrays.asList(provider)));
31         }
32     }

自定義的類MyTokenService是複製 DefaultTokenService程式碼

修改了重新整理token的方法

MyTokenService.java

 1 public class MyTokenService implements AuthorizationServerTokenServices, ResourceServerTokenServices,
 2         ConsumerTokenServices, InitializingBean {
 3     /**
 4      * 修改重新整理token方法,只更新token時間,不更換舊的token值
 5      * @param refreshTokenValue
 6      * @param tokenRequest
 7      * @return
 8      * @throws AuthenticationException
 9      */
10     @Override
11     @Transactional(noRollbackFor={InvalidTokenException.class, InvalidGrantException.class})
12     public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest)
13             throws AuthenticationException {
14 
15         。。。前面沒動
16 
17         OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
18         // 保留token原值
19         ((DefaultOAuth2AccessToken)accessToken).setValue(tokenRequest.getRequestParameters().get("access_token"));
20         tokenStore.storeAccessToken(accessToken, authentication);
21         if (!reuseRefreshToken) {
22             tokenStore.storeRefreshToken(refreshToken, authentication);
23         }
24         return accessToken;
25     }

重新啟動專案,重新整理token介面呼叫後,返回的還是原來的token值

作者:海綿般汲取
出處:https://www.cnblogs.com/gne-hwz/
版權:本文版權歸作者和部落格園共有
轉載:歡迎轉載,但未經作者同意,必須保留此段宣告;必須在文章中給出原文連線;否則必究法律責任