在OAuth2中 自定義tokenServices來提供個性化服務,每次刷新token並讓原token在5分鍾內有效


這樣寫有幾個好處:

  • 不需要使用攔截器來讓設備異地登錄失效,大大提升吞吐量
  • 每次登錄都刷新了access_token,並且加滿了過期時間,不會出現過期時間到了要重新登錄的問題。
  • 可以自定義在獲取新token后,讓原token5分鍾內仍有效

 

直接復制DefaultTokenServices代碼進行修改

 

 

所有的代碼保留,唯獨要修改的是createAccessToken這個方法

@Transactional
    public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {

        OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication);
        OAuth2RefreshToken refreshToken = null;
        if (existingAccessToken != null) {
            if (existingAccessToken.isExpired()) {
                if (existingAccessToken.getRefreshToken() != null) {
                    refreshToken = existingAccessToken.getRefreshToken();
                    // The token store could remove the refresh token when the
                    // access token is removed, but we want to
                    // be sure...
                    tokenStore.removeRefreshToken(refreshToken);
                }
                tokenStore.removeAccessToken(existingAccessToken);
            }
            else {
                // modified by pancg 2020-03-02
                // 根據當前開放平台功能設計調整為每次獲取新token並讓老token在5分鍾內有效

                // 1.這里是原來的實現
                // Re-store the access token in case the authentication has changed
                //tokenStore.storeAccessToken(existingAccessToken, authentication);
                //return existingAccessToken;

                // 2.讓原token在token更新后5分鍾內仍有效
                // Re-store the access token in case the authentication has changed
                tokenStore.storeAccessToken(createAccessTokenInNextFiveMinute(existingAccessToken, authentication), authentication);

                // 3.下面是創建新token並返回
                // Only create a new refresh token if there wasn't an existing one
                // associated with an expired access token.
                // Clients might be holding existing refresh tokens, so we re-use it in
                // the case that the old access token
                // expired.
                if (refreshToken == null) {
                    refreshToken = createRefreshToken(authentication);
                }
                // But the refresh token itself might need to be re-issued if it has
                // expired.
                else if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
                    ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken;
                    if (System.currentTimeMillis() > expiring.getExpiration().getTime()) {
                        refreshToken = createRefreshToken(authentication);
                    }
                }
                OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
                tokenStore.storeAccessToken(accessToken, authentication);
                // In case it was modified
                refreshToken = accessToken.getRefreshToken();
                if (refreshToken != null) {
                    tokenStore.storeRefreshToken(refreshToken, authentication);
                }
                return accessToken;
            }
        }

        // Only create a new refresh token if there wasn't an existing one
        // associated with an expired access token.
        // Clients might be holding existing refresh tokens, so we re-use it in
        // the case that the old access token
        // expired.
        if (refreshToken == null) {
            refreshToken = createRefreshToken(authentication);
        }
        // But the refresh token itself might need to be re-issued if it has
        // expired.
        else if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
            ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken;
            if (System.currentTimeMillis() > expiring.getExpiration().getTime()) {
                refreshToken = createRefreshToken(authentication);
            }
        }

        OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
        tokenStore.storeAccessToken(accessToken, authentication);
        // In case it was modified
        refreshToken = accessToken.getRefreshToken();
        if (refreshToken != null) {
            tokenStore.storeRefreshToken(refreshToken, authentication);
        }
        return accessToken;

    }

 

    /**
     * @description 創建一個使原token在接下來5分鍾有效的token
     * @added by pancg
     * @param
     * @return
     */
    private OAuth2AccessToken createAccessTokenInNextFiveMinute(OAuth2AccessToken existingAccessToken, OAuth2Authentication authentication) {
        final int validitySeconds = 5 * 60;
        DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(existingAccessToken.getValue());
        //DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString());
        //int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request());
        if (validitySeconds > 0) {
            token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L)));
        }
        token.setRefreshToken(existingAccessToken.getRefreshToken());
        token.setScope(authentication.getOAuth2Request().getScope());

        //return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token;
        return token;
    }

 

最后在AuthorizationServerConfig增加如下內容,其中endpoints.tokenServices(tokenServices(endpoints));就是把我們新寫的SingleTokenServices給配置進來。

@Override
   public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
      endpoints.tokenServices(tokenServices(endpoints));
      endpoints.authenticationManager(this.authenticationManager);
      endpoints.tokenStore(tokenStore());
      // 授權碼模式下,code存儲
//    endpoints.authorizationCodeServices(new JdbcAuthorizationCodeServices(dataSource));
      endpoints.authorizationCodeServices(redisAuthorizationCodeServices);
      if (storeWithJwt) {
         endpoints.accessTokenConverter(accessTokenConverter());
      }
   }

   private SingleTokenServices tokenServices(AuthorizationServerEndpointsConfigurer endpoints) {
      SingleTokenServices tokenServices = new SingleTokenServices();
      tokenServices.setTokenStore(tokenStore());
      tokenServices.setSupportRefreshToken(true);//支持刷新token
      tokenServices.setReuseRefreshToken(true);
      tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
      tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
      addUserDetailsService(tokenServices, this.userDetailsService);
      return tokenServices;
   }
   private void addUserDetailsService(SingleTokenServices tokenServices, UserDetailsService userDetailsService) {
      if (userDetailsService != null) {
         PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
         provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(
               userDetailsService));
         tokenServices.setAuthenticationManager(new ProviderManager(Arrays.asList(provider)));
      }
   }

  








參考:https://my.oschina.net/u/3768341/blog/2998273







免責聲明!

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



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