


Cara SpringBoot Security melaksanakan log keluar tunggal dan mengosongkan semua token
May 14, 2023 pm 01:43 PMKeperluan
Sistem A, B dan C boleh log masuk melalui perkhidmatan sso
Sistem A, B dan C memperoleh Atoken dan Btoken masing-masing , Ctoken tiga token
Selepas salah satu sistem log keluar secara aktif, dua sistem lain turut log keluar
Setakat ini semua Atoken dan Btoken , Ctoken tidak sah
Token rekod
fail pom memperkenalkan kebergantungan
Kebergantungan pangkalan data Redis
hutool: digunakan untuk menghuraikan 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>
kelas storan token melaksanakan AuthJdbcTokenStore
TokenStore>mewarisi JdbcToken>
- Gunakan nama pengguna pengguna log masuk sebagai kunci Redis
- Oleh kerana akan terdapat berbilang sistem di mana pengguna log masuk, nilai menggunakan Jenis senarai redis untuk menyimpan token
- Tetapkan masa sah untuk memastikan bahawa ia tidak kurang daripada masa sah maksimum token dalam senarai
@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(OAuth3AccessToken token, OAuth3Authentication 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; } }
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;
- Melalui kaedah Pembinaan Jbc. dalam DataSource
- Buat TokenStore Gunakan AuthJdbcTokenStore untuk melaksanakan
- tokenServices Tambah TokenStore
- <🎜 Tambah 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) ; } ... }
- Warisi SimpleUrlLogoutSuccessHandler
- Dapatkan nama pengguna Dapatkan senarai token yang disimpan dalam Redis semasa log masuk
- Rentetan token ditukar kepada OAuth3AccessToken
- Gunakan tokenStore untuk memadam 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) { OAuth3AccessToken token = tokenStore.readAccessToken(tokenValue); if (Objects.nonNull(token)) { tokenStore.removeAccessToken(token); } } redisTemplate.delete(userTokensKey); super.handle(request, response, authentication); } } }
Salin selepas log masukUntuk menyelesaikan masa log keluar Terlalu lama
Senario: Selepas projek telah berjalan untuk satu tempoh masa, didapati bahawa masa log keluar semakin perlahan dan semakin perlahan
Masalah: Melalui penyahpepijatan, didapati bahawa memakan masa adalah terutamanya dalam tempoh pemadaman token
tokenStore.removeAccessToken(token);
Sebab: Semakin masa berlalu, semakin banyak dan lebih banyak token dan jadual storan token oauth_access_token menjadi luar biasa besar, jadi kecekapan pemadaman sangat lemah
Penyelesaian: Gunakan TokenStore lain, atau kosongkan data jadual oauth_access_token
Atas ialah kandungan terperinci Cara SpringBoot Security melaksanakan log keluar tunggal dan mengosongkan semua token. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Artikel Panas

Alat panas Tag

Artikel Panas

Tag artikel panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

17 cara untuk menyelesaikan skrin biru kernel_security_check_failure

Bagaimana Springboot menyepadukan Jasypt untuk melaksanakan penyulitan fail konfigurasi

Bagaimana untuk menyelesaikan masalah token log masuk tidak sah

Cara menggunakan Redis untuk melaksanakan kunci teragih dalam SpringBoot

Bagaimana untuk menyelesaikan masalah bahawa springboot tidak boleh mengakses fail selepas membacanya ke dalam pakej balang

Analisis perbandingan dan perbezaan antara SpringBoot dan SpringMVC

Perkara yang perlu dilakukan jika token log masuk tidak sah

Bagaimana SpringBoot menyesuaikan Redis untuk melaksanakan penyirian cache
