Performance improvement of token cleanup:
an alternative token cleanup mechanism designed to maintain a very compact memory footprint while performing cleanup in consecutive runs of the cleanup thread. This serves to address OutOfMemoryException issues of the original token cleanup mechanism when process is under load. Also, added cleanup of the authentication_holder table. Conflicts: openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthenticationHolderEntity.java openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.javapull/661/merge
parent
aadc011104
commit
287dce5c02
|
@ -34,7 +34,8 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
|||
@Table(name = "authentication_holder")
|
||||
@NamedQueries ({
|
||||
@NamedQuery(name = "AuthenticationHolderEntity.getByAuthentication", query = "select a from AuthenticationHolderEntity a where a.authentication = :authentication"),
|
||||
@NamedQuery(name = "AuthenticationHolderEntity.getAll", query = "select a from AuthenticationHolderEntity a")
|
||||
@NamedQuery(name = "AuthenticationHolderEntity.getAll", query = "select a from AuthenticationHolderEntity a"),
|
||||
@NamedQuery(name = "AuthenticationHolderEntity.getUnusedAuthenticationHolders", query = "select a from AuthenticationHolderEntity a where a.id not in (select t.authenticationHolderId from OAuth2AccessTokenEntity t) and a.id not in (select r.authenticationHolderId from OAuth2RefreshTokenEntity r)")
|
||||
})
|
||||
|
||||
public class AuthenticationHolderEntity {
|
||||
|
|
|
@ -58,6 +58,7 @@ import com.nimbusds.jwt.JWTParser;
|
|||
@Table(name = "access_token")
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "OAuth2AccessTokenEntity.getAll", query = "select a from OAuth2AccessTokenEntity a"),
|
||||
@NamedQuery(name = "OAuth2AccessTokenEntity.getAllExpiredByDate", query = "select a from OAuth2AccessTokenEntity a where a.expiration <= :date"),
|
||||
@NamedQuery(name = "OAuth2AccessTokenEntity.getByRefreshToken", query = "select a from OAuth2AccessTokenEntity a where a.refreshToken = :refreshToken"),
|
||||
@NamedQuery(name = "OAuth2AccessTokenEntity.getByClient", query = "select a from OAuth2AccessTokenEntity a where a.client = :client"),
|
||||
@NamedQuery(name = "OAuth2AccessTokenEntity.getByAuthentication", query = "select a from OAuth2AccessTokenEntity a where a.authenticationHolder.authentication = :authentication"),
|
||||
|
|
|
@ -50,6 +50,7 @@ import com.nimbusds.jwt.JWTParser;
|
|||
@Table(name = "refresh_token")
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "OAuth2RefreshTokenEntity.getAll", query = "select r from OAuth2RefreshTokenEntity r"),
|
||||
@NamedQuery(name = "OAuth2RefreshTokenEntity.getAllExpiredByDate", query = "select r from OAuth2RefreshTokenEntity r where r.expiration <= :date"),
|
||||
@NamedQuery(name = "OAuth2RefreshTokenEntity.getByClient", query = "select r from OAuth2RefreshTokenEntity r where r.client = :client"),
|
||||
@NamedQuery(name = "OAuth2RefreshTokenEntity.getByTokenValue", query = "select r from OAuth2RefreshTokenEntity r where r.value = :tokenValue"),
|
||||
@NamedQuery(name = "OAuth2RefreshTokenEntity.getByAuthentication", query = "select r from OAuth2RefreshTokenEntity r where r.authenticationHolder.authentication = :authentication")
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package org.mitre.oauth2.repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.mitre.oauth2.model.AuthenticationHolderEntity;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
|
||||
|
@ -33,5 +35,8 @@ public interface AuthenticationHolderRepository {
|
|||
public void remove(AuthenticationHolderEntity a);
|
||||
|
||||
public AuthenticationHolderEntity save(AuthenticationHolderEntity a);
|
||||
|
||||
public List<AuthenticationHolderEntity> getOrphanedAuthenticationHolders();
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -57,5 +57,9 @@ public interface OAuth2TokenRepository {
|
|||
public Set<OAuth2AccessTokenEntity> getAllAccessTokens();
|
||||
|
||||
public Set<OAuth2RefreshTokenEntity> getAllRefreshTokens();
|
||||
|
||||
public Set<OAuth2AccessTokenEntity> getAllExpiredAccessTokens();
|
||||
|
||||
public Set<OAuth2RefreshTokenEntity> getAllExpiredRefreshTokens();
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package org.mitre.oauth2.repository.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
@ -32,6 +34,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
@Transactional
|
||||
public class JpaAuthenticationHolderRepository implements AuthenticationHolderRepository {
|
||||
|
||||
private static final int MAXEXPIREDRESULTS = 1000;
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager manager;
|
||||
|
||||
|
@ -80,5 +84,14 @@ public class JpaAuthenticationHolderRepository implements AuthenticationHolderRe
|
|||
public AuthenticationHolderEntity save(AuthenticationHolderEntity a) {
|
||||
return JpaUtil.saveOrUpdate(a.getId(), manager, a);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public List<AuthenticationHolderEntity> getOrphanedAuthenticationHolders() {
|
||||
TypedQuery<AuthenticationHolderEntity> query = manager.createNamedQuery("AuthenticationHolderEntity.getUnusedAuthenticationHolders", AuthenticationHolderEntity.class);
|
||||
query.setMaxResults(MAXEXPIREDRESULTS);
|
||||
List<AuthenticationHolderEntity> unusedAuthenticationHolders = query.getResultList();
|
||||
return unusedAuthenticationHolders;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
******************************************************************************/
|
||||
package org.mitre.oauth2.repository.impl;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -36,6 +37,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
@Repository
|
||||
public class JpaOAuth2TokenRepository implements OAuth2TokenRepository {
|
||||
|
||||
private static final int MAXEXPIREDRESULTS = 1000;
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager manager;
|
||||
|
||||
|
@ -178,5 +181,21 @@ public class JpaOAuth2TokenRepository implements OAuth2TokenRepository {
|
|||
List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList();
|
||||
return JpaUtil.getSingleResult(accessTokens);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<OAuth2AccessTokenEntity> getAllExpiredAccessTokens() {
|
||||
TypedQuery<OAuth2AccessTokenEntity> query = manager.createNamedQuery("OAuth2AccessTokenEntity.getAllExpiredByDate", OAuth2AccessTokenEntity.class);
|
||||
query.setParameter("date", new Date());
|
||||
query.setMaxResults(MAXEXPIREDRESULTS);
|
||||
return new LinkedHashSet<OAuth2AccessTokenEntity>(query.getResultList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<OAuth2RefreshTokenEntity> getAllExpiredRefreshTokens() {
|
||||
TypedQuery<OAuth2RefreshTokenEntity> query = manager.createNamedQuery("OAuth2RefreshTokenEntity.getAllExpiredByDate", OAuth2RefreshTokenEntity.class);
|
||||
query.setParameter("date", new Date());
|
||||
query.setMaxResults(MAXEXPIREDRESULTS);
|
||||
return new LinkedHashSet<OAuth2RefreshTokenEntity>(query.getResultList());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -367,7 +367,13 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi
|
|||
Collection<OAuth2AccessTokenEntity> accessTokens = getExpiredAccessTokens();
|
||||
logger.info("Found " + accessTokens.size() + " expired access tokens");
|
||||
for (OAuth2AccessTokenEntity oAuth2AccessTokenEntity : accessTokens) {
|
||||
revokeAccessToken(oAuth2AccessTokenEntity);
|
||||
try {
|
||||
revokeAccessToken(oAuth2AccessTokenEntity);
|
||||
} catch (IllegalArgumentException e) {
|
||||
//An ID token is deleted with its corresponding access token, but then the ID token is on the list of expired tokens as well and there is
|
||||
//nothing in place to distinguish it from any other.
|
||||
//An attempt to delete an already deleted token returns an error, stopping the cleanup dead. We need it to keep going.
|
||||
}
|
||||
}
|
||||
|
||||
Collection<OAuth2RefreshTokenEntity> refreshTokens = getExpiredRefreshTokens();
|
||||
|
@ -375,28 +381,24 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi
|
|||
for (OAuth2RefreshTokenEntity oAuth2RefreshTokenEntity : refreshTokens) {
|
||||
revokeRefreshToken(oAuth2RefreshTokenEntity);
|
||||
}
|
||||
|
||||
Collection<AuthenticationHolderEntity> authHolders = getOrphanedAuthenticationHolders();
|
||||
logger.info("Found " + authHolders.size() + " orphaned authentication holders");
|
||||
for(AuthenticationHolderEntity authHolder : authHolders) {
|
||||
authenticationHolderRepository.remove(authHolder);
|
||||
}
|
||||
}
|
||||
|
||||
private Predicate<OAuth2AccessTokenEntity> isAccessTokenExpired = new Predicate<OAuth2AccessTokenEntity>() {
|
||||
@Override
|
||||
public boolean apply(OAuth2AccessTokenEntity input) {
|
||||
return (input != null && input.isExpired());
|
||||
}
|
||||
};
|
||||
|
||||
private Predicate<OAuth2RefreshTokenEntity> isRefreshTokenExpired = new Predicate<OAuth2RefreshTokenEntity>() {
|
||||
@Override
|
||||
public boolean apply(OAuth2RefreshTokenEntity input) {
|
||||
return (input != null && input.isExpired());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private Collection<OAuth2AccessTokenEntity> getExpiredAccessTokens() {
|
||||
return Sets.filter(Sets.newHashSet(tokenRepository.getAllAccessTokens()), isAccessTokenExpired);
|
||||
return Sets.newHashSet(tokenRepository.getAllExpiredAccessTokens());
|
||||
}
|
||||
|
||||
private Collection<OAuth2RefreshTokenEntity> getExpiredRefreshTokens() {
|
||||
return Sets.filter(Sets.newHashSet(tokenRepository.getAllRefreshTokens()), isRefreshTokenExpired);
|
||||
return Sets.newHashSet(tokenRepository.getAllExpiredRefreshTokens());
|
||||
}
|
||||
|
||||
private Collection<AuthenticationHolderEntity> getOrphanedAuthenticationHolders() {
|
||||
return Sets.newHashSet(authenticationHolderRepository.getOrphanedAuthenticationHolders());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
|
Loading…
Reference in New Issue