Heim >Java >javaLernprogramm >Wie SpringBoot Security Single Sign-out implementiert und alle Token löscht

Wie SpringBoot Security Single Sign-out implementiert und alle Token löscht

WBOY
WBOYnach vorne
2023-05-14 13:43:112085Durchsuche

Anforderungen

  • A-, B- und C-Systeme melden sich über den SSO-Dienst an meldet sich aktiv ab. Die anderen beiden Systeme haben sich ebenfalls abgemeldet. Wird zum Parsen des Tokens verwendet

    Denn es wird mehrere Systeme geben, die Der Benutzer meldet sich an, daher verwendet der Wert die Redis-Liste Typ zum Speichern des Tokens
  • Stellen Sie die Gültigkeitszeit ein, um sicherzustellen, dass sie nicht kürzer als die maximale Gültigkeitszeit des Tokens in der Liste ist
  • <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>

    oauth_access_token Verwenden Sie JdbcTokenStore Um Token zu speichern, müssen Sie eine neue Tabelle hinzufügen kenStore
  • tokenServices TokenStore hinzufügen

endpoints TokenServices hinzufügen

    @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;
        }
    }
  • clear token

  • inherits SimpleUrlLogoutSuccessHandler

Benutzernamen abrufen. userName

  • Rufen Sie beim Anmelden die in Redis gespeicherte Token-Liste ab

  • Token-Zeichenfolge wird in OAuth3AccessToken konvertiert

  • TokenStore verwenden, um das Token zu löschen

  • 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;
  • Das Problem der übermäßigen Abmeldezeit wurde behoben

    Szenario: Nachdem das Projekt eine Zeit lang ausgeführt wurde, wird festgestellt, dass das Die Abmeldezeit wird immer langsamer
Problem: Beim Debuggen wurde festgestellt, dass der Zeitaufwand hauptsächlich im Zeitraum des Löschens von Token liegt

@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)
        ;
    }
	...
}

Ursache: Mit der Zeit gibt es immer mehr Token in der Speichertabelle oauth_access_token ist ungewöhnlich groß geworden, daher ist die Löscheffizienz sehr schlecht

Lösung: Verwenden Sie einen anderen TokenStore oder löschen Sie die Tabellendaten von oauth_access_token

    Das obige ist der detaillierte Inhalt vonWie SpringBoot Security Single Sign-out implementiert und alle Token löscht. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen