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 如果你想存储那么我认为你可以制作一个调度程序来删除令牌。
我已经为 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 如果你想存储那么我认为你可以制作一个调度程序来删除令牌。