最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot Security實現(xiàn)單點登出并清除所有token

 更新時間:2023年01月14日 13:47:56   作者:我有一只肥螳螂  
Spring Security是一個功能強大且高度可定制的身份驗證和訪問控制框架。提供了完善的認(rèn)證機制和方法級的授權(quán)功能。是一款非常優(yōu)秀的權(quán)限管理框架。它的核心是一組過濾器鏈,不同的功能經(jīng)由不同的過濾器

需求

  • A、B、C 系統(tǒng)通過 sso 服務(wù)實現(xiàn)登錄
  • A、B、C 系統(tǒng)分別獲取 Atoken、Btoken、Ctoken 三個 token
  • 其中某一個系統(tǒng)主動登出后,其他兩個系統(tǒng)也登出
  • 至此全部 Atoken、Btoken、Ctoken 失效

記錄token

pom 文件引入依賴

  • Redis數(shù)據(jù)庫依賴
  • hutool:用于解析token
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
   <groupId>cn.hutool</groupId>
   <artifactId>hutool-all</artifactId>
   <version>5.7.13</version>
</dependency>

token 存儲類 實現(xiàn) AuthJdbcTokenStore

  • TokenStore 繼承 JdbcTokenStore
  • 使用登錄用戶的用戶名 username 做 Redis 的 key
  • 因為用戶登錄的系統(tǒng)會有多個,所以 value 使用 Redis 的列表類型來存儲 token
  • 設(shè)置有效時間,保證不少于 list 里 token 的最大有效時間
@Component
public class AuthJdbcTokenStore extends JdbcTokenStore {
    public static final String USER_HAVE_TOKEN = "user-tokens:";
    @Resource
    RedisTemplate redisTemplate;
    public AuthJdbcTokenStore(DataSource connectionFactory) {
        super(connectionFactory);
    }
    @Override
    public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
        super.storeAccessToken(token, authentication);
        if (Optional.ofNullable(authentication.getUserAuthentication()).isPresent()) {
            User user = (User) authentication.getUserAuthentication().getPrincipal();
            String userTokensKey = USER_HAVE_TOKEN + user.getUsername();
            String tokenValue = token.getValue();
            redisTemplate.opsForList().leftPush(userTokensKey, tokenValue);
            Long seconds = redisTemplate.opsForValue().getOperations().getExpire(userTokensKey);
            Long tokenExpTime = getExpTime(tokenValue);
            Long expTime = seconds < tokenExpTime ? tokenExpTime : seconds;
            redisTemplate.expire(userTokensKey, expTime, TimeUnit.SECONDS);
        }
    }
    private long getExpTime(String accessToken) {
        JWT jwt = JWTUtil.parseToken(accessToken);
        cn.hutool.json.JSONObject jsonObject = jwt.getPayload().getClaimsJson();
        long nowTime = Instant.now().getEpochSecond();
        long expEndTime = jsonObject.getLong("exp");
        long expTime = (expEndTime - nowTime);
        return expTime;
    }
}

oauth_access_token 使用 JdbcTokenStore 存儲 token 需要新增表

CREATE TABLE `oauth_access_token` (
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `token_id` varchar(255) DEFAULT NULL,
  `token` blob,
  `authentication_id` varchar(255) DEFAULT NULL,
  `user_name` varchar(255) DEFAULT NULL,
  `client_id` varchar(255) DEFAULT NULL,
  `authentication` blob,
  `refresh_token` varchar(255) DEFAULT NULL,
  UNIQUE KEY `authentication_id` (`authentication_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

AuthorizationServerConfigurerAdapter 使用 AuthJdbcTokenStore 做 token 存儲

  • 引入 DataSource,因為 JdbcTokenStore 的構(gòu)造方法必須傳入 DataSource
  • 創(chuàng)建按 TokenStore,用 AuthJdbcTokenStore 實現(xiàn)
  • tokenServices 添加 TokenStore
  • endpoints 添加 tokenServices
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private DataSource dataSource;
	...
    @Bean
    public TokenStore tokenStore() {
        JdbcTokenStore tokenStore = new AuthJdbcTokenStore(dataSource);
        return tokenStore;
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStore());
        endpoints
                .authenticationManager(authenticationManager)
                .tokenServices(tokenServices)
                .accessTokenConverter(converter)
        ;
    }
	...
}

清除token

  • 繼承 SimpleUrlLogoutSuccessHandler
  • 獲取用戶名 userName
  • 獲取登錄時存儲在 Redis 的 token 列表
  • token 字符串轉(zhuǎn)換成 OAuth2AccessToken
  • 使用 tokenStore 刪除 token
@Component
public class AuthLogoutSuccessHandler1 extends SimpleUrlLogoutSuccessHandler {
    String USER_HAVE_TOKEN = AuthJdbcTokenStore.USER_HAVE_TOKEN;
    @Resource
    RedisTemplate redisTemplate;
    @Resource
    TokenStore tokenStore;
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        if (!Objects.isNull(authentication)) {
            String userName = authentication.getName();
            String userTokensKey = USER_HAVE_TOKEN + userName;
            Long size = redisTemplate.opsForList().size(userTokensKey);
            List<String> list = redisTemplate.opsForList().range(userTokensKey, 0, size);
            for (String tokenValue : list) {
                OAuth2AccessToken token = tokenStore.readAccessToken(tokenValue);
                if (Objects.nonNull(token)) {
                    tokenStore.removeAccessToken(token);
                }
            }
            redisTemplate.delete(userTokensKey);
            super.handle(request, response, authentication);
        }
    }
}

解決登出時長過長

場景:項目運行一段時間后,發(fā)現(xiàn)登出時間越來越慢

問題:通過 debug 發(fā)現(xiàn)耗時主要在刪除 token 那一段

tokenStore.removeAccessToken(token);

原因:隨著時間推移,token 越來越多,token 存儲表 oauth_access_token 變得異常的大,所以刪除效率非常差

解決辦法:使用其他 TokenStore,或者清除 oauth_access_token 的表數(shù)據(jù)

到此這篇關(guān)于SpringBoot Security實現(xiàn)單點登出并清除所有token的文章就介紹到這了,更多相關(guān)SpringBoot Security單點登出內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot + FreeMarker 實現(xiàn)動態(tài)Word文檔導(dǎo)出功能

    Spring Boot + FreeMarker 實現(xiàn)動態(tài)Word文檔導(dǎo)出功能

    Spring Boot與FreeMarker的組合,為開發(fā)者提供了一個強大的平臺,可以輕松實現(xiàn)動態(tài)Word文檔的導(dǎo)出,本文將指導(dǎo)你如何使用Spring Boot與FreeMarker模板引擎,創(chuàng)建一個簡單的應(yīng)用,用于根據(jù)數(shù)據(jù)庫數(shù)據(jù)動態(tài)生成Word文檔并下載,感興趣的朋友一起看看吧
    2024-06-06
  • MyBatis使用注解開發(fā)實現(xiàn)步驟解析

    MyBatis使用注解開發(fā)實現(xiàn)步驟解析

    這篇文章主要介紹了MyBatis使用注解開發(fā)實現(xiàn)步驟解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • java壓縮zip文件中文亂碼問題解決方法

    java壓縮zip文件中文亂碼問題解決方法

    這篇文章主要介紹了java壓縮zip文件中文亂碼問題的解決方法,需要的朋友可以參考下
    2014-07-07
  • 關(guān)于@Query注解的用法(Spring Data JPA)

    關(guān)于@Query注解的用法(Spring Data JPA)

    這篇文章主要介紹了關(guān)于@Query注解的用法(Spring Data JPA),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 在Spring?Boot中啟用HTTPS的方法

    在Spring?Boot中啟用HTTPS的方法

    本文介紹了在Spring Boot項目中啟用HTTPS的步驟,從生成SSL證書開始,到配置Spring Boot。HTTPS是保護Web應(yīng)用程序安全的基石之一,而Spring Boot則提供了相對簡易的途徑來配置它,感興趣的朋友跟隨小編一起看看吧
    2024-02-02
  • 關(guān)于log4j2的異步日志輸出方式

    關(guān)于log4j2的異步日志輸出方式

    這篇文章主要介紹了關(guān)于log4j2的異步日志輸出方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java二叉樹中LCA問題解決方法兩則

    Java二叉樹中LCA問題解決方法兩則

    這篇文章主要介紹了Java二叉樹中LCA問題解決方法,總的來說這并不是一道難題,那為什么要拿出這道題介紹?拿出這道題真正想要傳達的是解題的思路,以及不斷優(yōu)化探尋最優(yōu)解的過程。希望通過這道題能給你帶來一種解題優(yōu)化的思路
    2022-12-12
  • 基于SpringBoot整合oauth2實現(xiàn)token認(rèn)證

    基于SpringBoot整合oauth2實現(xiàn)token認(rèn)證

    這篇文章主要介紹了基于SpringBoot整合oauth2實現(xiàn)token 認(rèn)證,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • java開發(fā)MVC三層架構(gòu)上再加一層Manager層原理詳解

    java開發(fā)MVC三層架構(gòu)上再加一層Manager層原理詳解

    這篇文章主要為大家介紹了MVC三層架構(gòu)中再加一層Manager層原理的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-10-10
  • spring boot使用i18n時properties文件中文亂碼問題的解決方法

    spring boot使用i18n時properties文件中文亂碼問題的解決方法

    這篇文章主要介紹了spring boot使用i18n時properties文件中文亂碼問題的解決方法,需要的朋友可以參考下
    2017-11-11

最新評論

盖州市| 孟村| 讷河市| 北辰区| 望奎县| 丹东市| 南郑县| 五峰| 宁武县| 门头沟区| 鹤庆县| 青州市| 安岳县| 泸西县| 同德县| 长宁区| 五家渠市| 浮山县| 婺源县| 东丰县| 汽车| 浪卡子县| 澄江县| 昭通市| 澎湖县| 永定县| 斗六市| 上饶市| 沐川县| 肇州县| 宜章县| 鄯善县| 繁峙县| 陇川县| 平原县| 海宁市| 社旗县| 南平市| 文水县| 吉木乃县| 南雄市|