spring 安全性中是否有一项功能可以在令牌到期后自动从数据库中删除令牌

Is there a functionality in spring security to auto remove token from db once expiry time of that token is completed

我已经为 spring 安全实施了以下代码。 我正在使用 spring 版本 2.3.0.BUILD-SNAPSHOT 和安全性 oauth-2 版本 2.3.0.RELEASE 是否可以在其到期时间结束后删除/撤销授予的访问令牌?如果是这样,哪个 class/method 应该放在什么地方,以实现目标?

AuthenticationService.java

package com.oauth.config;
import java.util.Arrays;    
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.oauth.model.UserInfo;
import com.oauth.service.UserService;

@Service("authenticationService")
public class AuthenticationService implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        HttpServletRequest request = (
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

            System.out.println("userId: " + request.getParameter("userId"));

            UserInfo user = null;
        try {
            user = userService.getUserInfoByUserName(username);
            GrantedAuthority authority = new SimpleGrantedAuthority(user.getRole());
            return new User(user.getUserName(), user.getPassword(), Arrays.asList(authority));
        } catch (Exception e) {
            e.printStackTrace();
            throw new UsernameNotFoundException("Invalid user id or password.");
        }       
    }
}

Outh2Configuration.java

package com.oauth.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

@Configuration
public class OAuth2Configuration {

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        /*
         * @Autowired private CustomLogoutSuccessHandler customLogoutSuccessHandler;
         */

        @Override
        public void configure(HttpSecurity http) throws Exception {

            http.authorizeRequests().and()

            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            //.and().logout().logoutUrl("/oauth/logout").logoutSuccessHandler(customLogoutSuccessHandler)
            .and().authorizeRequests()
            .antMatchers("/noAuth/**","/customerNoAuth/**" ,"/oauth/token").permitAll()
                        .anyRequest().denyAll()
            .and().csrf().disable()
            .exceptionHandling();
        }
    }



 @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter implements EnvironmentAware {

        private static final String PROP_CLIENTID = "client";
        private static final String PROP_SECRET = "secret";
        private static final int PROP_TOKEN_VALIDITY_SECONDS = 60 * 60 * 24 * 7;

        @Autowired
        private DataSource dataSource;

        @Bean
        public TokenStore tokenStore() {
            return new JdbcTokenStore(dataSource);
        }

        @Autowired
        @Qualifier("myAuthenticationManager")
        private AuthenticationManager authenticationManager;

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                //.tokenStore(tokenStore())
                .authenticationManager(authenticationManager)
                .tokenServices(tokenServices());
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

            String secretEncoded = passwordEncoder().encode(PROP_SECRET);

            clients
                .inMemory()
                .withClient(PROP_CLIENTID)
                .scopes("read", "write", "trust")
                .authorities("ADMIN", "USER")
                .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")                    
                .secret(secretEncoded)
                .accessTokenValiditySeconds(PROP_TOKEN_VALIDITY_SECONDS)
                .refreshTokenValiditySeconds(PROP_TOKEN_VALIDITY_SECONDS);

        }

        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }

        @Override
        public void setEnvironment(Environment arg0) {
        }

        @Bean
        @Primary
        public DefaultTokenServices tokenServices() {
            CustomTokenService defaultTokenServices = new CustomTokenService();
            defaultTokenServices.setTokenStore(tokenStore());
            defaultTokenServices.setSupportRefreshToken(true);
            return defaultTokenServices;
        }
    }
}

WebSecurityConfiguration.java

package com.oauth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthenticationService authenticateService;

    @Bean(name="myAuthenticationManager")
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web
        .ignoring()
        .antMatchers("/noAuth/**",
                "/customerNoAuth/**",
                "/state/**",
                "/country/**",
                "/violation/**",
                "/ticketViolation/**",
                "/api/zipcode/**");
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        auth
        .userDetailsService(authenticateService)
        .passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

CustomTokenService.java

package com.oauth.config;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.transaction.annotation.Transactional;

import lombok.Synchronized;

public class CustomTokenService extends DefaultTokenServices {

    private final Logger log = LogManager.getFormatterLogger(getClass());

    @Override
    @Transactional
    @Synchronized
    public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {
        try {
            int count = 0;
            OAuth2AccessToken accessToken = null;

                try{
                    accessToken = super.createAccessToken(authentication);
                }catch(DuplicateKeyException e){
                    do{
                        log.info("===========DuplicateKeyException===========");
                        log.info(String.format("Duplicate user found for %s",authentication.getUserAuthentication().getPrincipal()));
                        Thread.sleep(500);
                        try {
                            return accessToken = super.createAccessToken(authentication);
                        } catch (DuplicateKeyException e2) {
                            ++count;
                            log.error("Attempt count " + count);
                        }
                    }while(count<=5);
                }
            return accessToken;
        }catch (Exception ex) {
            log.info(String.format("Exception while creating access token %s",ex));
        }
        return null;
    }    
}

CustomLogoutSuccessHandler.java

package com.oauth.config;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.authentication.AbstractAuthenticationTargetUrlRequestHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

/**
 * Spring Security logout handler
 */
//@Component
public class CustomLogoutSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler implements LogoutSuccessHandler {

    private static final String BEARER_AUTHENTICATION = "bearer ";
    private static final String HEADER_AUTHORIZATION = "authorization";

    @Autowired
    private TokenStore tokenStore;

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, 
            Authentication authentication) throws IOException, ServletException {

        String token = request.getHeader(HEADER_AUTHORIZATION);

        if (token != null && token.startsWith(BEARER_AUTHENTICATION)) {

            String accessToken = token.substring(token.indexOf(" ") + 1);
            OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(accessToken);

            if (oAuth2AccessToken != null) {
                tokenStore.removeAccessToken(oAuth2AccessToken);
            }
        }

        response.setStatus(HttpServletResponse.SC_OK);
    }

}

你不应该在你的 DB.If 中存储令牌任何人都可以访问你的数据库,他可以轻松访问每个 data.Again 如果你想存储那么我认为你可以制作一个调度程序来删除令牌。