Maison >Java >javaDidacticiel >Comment SpringBoot Security implémente la déconnexion unique et efface tous les jetons
Les systèmes A, B et C implémentent la connexion via le service sso
A, les systèmes B et C obtiennent respectivement Atoken, Btoken et Ctoken
# 🎜🎜#
<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>la classe de stockage de jetons implémente AuthJdbcTokenStore
Utiliser la connexion Le nom d'utilisateur de l'utilisateur est utilisé comme clé Redis
Définissez la durée de validité pour vous assurer qu'elle n'est pas inférieure à la durée de validité maximale du jeton dans la liste
@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; } }
oauth_access_token L'utilisation de JdbcTokenStore pour stocker les jetons nécessite un nouveau L'ajout d'une table
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;
Présentation de DataSource, car la méthode de construction de JdbcTokenStore doit passer dans DataSource#🎜 🎜## 🎜🎜#
@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) ; } ... }# 🎜🎜# Effacer le jeton
Inherits SimpleUrlLogoutSuccessHandler#🎜 🎜##🎜🎜 #
#🎜 🎜#
Obtenir la liste des jetons stockée dans Redis lors de la connexionLa chaîne de jetons est convertie en OAuth3AccessToken
@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); } } }Solution pour se déconnecter Trop longtemps
tokenStore.removeAccessToken(token);# 🎜🎜#Cause : Au fil du temps, il y a de plus en plus de jetons, et la table de stockage des jetons oauth_access_token devient anormalement grande, donc l'efficacité de la suppression est très mauvaise
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!