diff --git a/build.gradle b/build.gradle index f158b52a6..7ad9b0fb9 100644 --- a/build.gradle +++ b/build.gradle @@ -366,8 +366,9 @@ subprojects { implementation group: 'com.alibaba', name: 'druid', version: "${druidVersion}" implementation group: 'com.alibaba', name: 'druid-spring-boot-starter', version: "${druidspringbootstarterVersion}" implementation group: 'redis.clients', name: 'jedis', version: "${jedisVersion}" - implementation group: 'org.ehcache', name: 'ehcache', version: "${ehcacheVersion}" + //implementation group: 'org.ehcache', name: 'ehcache', version: "${ehcacheVersion}" //implementation group: 'org.liquibase', name: 'liquibase-core', version: '4.3.5' + implementation group: 'com.github.ben-manes.caffeine', name: 'caffeine', version: "${caffeineVersion}" //mybatis implementation group: 'org.mybatis', name: 'mybatis', version: "${mybatisVersion}" diff --git a/config/build_docker.gradle b/config/build_docker.gradle index edb199b0b..4135bac22 100644 --- a/config/build_docker.gradle +++ b/config/build_docker.gradle @@ -318,9 +318,9 @@ subprojects { implementation group: 'com.alibaba', name: 'druid', version: "${druidVersion}" implementation group: 'com.alibaba', name: 'druid-spring-boot-starter', version: "${druidspringbootstarterVersion}" implementation group: 'redis.clients', name: 'jedis', version: "${jedisVersion}" - implementation group: 'org.ehcache', name: 'ehcache', version: "${ehcacheVersion}" + //implementation group: 'org.ehcache', name: 'ehcache', version: "${ehcacheVersion}" //implementation group: 'org.liquibase', name: 'liquibase-core', version: '4.3.5' - + implementation group: 'com.github.ben-manes.caffeine', name: 'caffeine', version: "${caffeineVersion}" //mybatis implementation group: 'org.mybatis', name: 'mybatis', version: "${mybatisVersion}" implementation group: 'org.mybatis', name: 'mybatis-spring', version: "${mybatisspringVersion}" diff --git a/config/build_jar.gradle b/config/build_jar.gradle index bf17e66b3..3c6b77add 100644 --- a/config/build_jar.gradle +++ b/config/build_jar.gradle @@ -318,9 +318,9 @@ subprojects { implementation group: 'com.alibaba', name: 'druid', version: "${druidVersion}" implementation group: 'com.alibaba', name: 'druid-spring-boot-starter', version: "${druidspringbootstarterVersion}" implementation group: 'redis.clients', name: 'jedis', version: "${jedisVersion}" - implementation group: 'org.ehcache', name: 'ehcache', version: "${ehcacheVersion}" + //implementation group: 'org.ehcache', name: 'ehcache', version: "${ehcacheVersion}" //implementation group: 'org.liquibase', name: 'liquibase-core', version: '4.3.5' - + implementation group: 'com.github.ben-manes.caffeine', name: 'caffeine', version: "${caffeineVersion}" //mybatis implementation group: 'org.mybatis', name: 'mybatis', version: "${mybatisVersion}" implementation group: 'org.mybatis', name: 'mybatis-spring', version: "${mybatisspringVersion}" diff --git a/config/build_standard.gradle b/config/build_standard.gradle index 10201f655..86318adb6 100644 --- a/config/build_standard.gradle +++ b/config/build_standard.gradle @@ -353,9 +353,9 @@ subprojects { implementation group: 'com.alibaba', name: 'druid', version: "${druidVersion}" implementation group: 'com.alibaba', name: 'druid-spring-boot-starter', version: "${druidspringbootstarterVersion}" implementation group: 'redis.clients', name: 'jedis', version: "${jedisVersion}" - implementation group: 'org.ehcache', name: 'ehcache', version: "${ehcacheVersion}" + //implementation group: 'org.ehcache', name: 'ehcache', version: "${ehcacheVersion}" //implementation group: 'org.liquibase', name: 'liquibase-core', version: '4.3.5' - + implementation group: 'com.github.ben-manes.caffeine', name: 'caffeine', version: "${caffeineVersion}" //mybatis implementation group: 'org.mybatis', name: 'mybatis', version: "${mybatisVersion}" implementation group: 'org.mybatis', name: 'mybatis-spring', version: "${mybatisspringVersion}" diff --git a/gradle.properties b/gradle.properties index b845f60dd..b0d5cff43 100644 --- a/gradle.properties +++ b/gradle.properties @@ -81,6 +81,7 @@ druidVersion =1.2.8 druidspringbootstarterVersion =1.2.8 jedisVersion =3.7.0 ehcacheVersion =3.9.6 +caffeineVersion =2.9.2 mybatisVersion =3.5.7 mybatisspringVersion =2.0.6 #saml diff --git a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/online/InMemoryOnlineTicketServices.java b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/online/InMemoryOnlineTicketServices.java index 12f14670f..ea83c0151 100644 --- a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/online/InMemoryOnlineTicketServices.java +++ b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/online/InMemoryOnlineTicketServices.java @@ -19,22 +19,23 @@ package org.maxkey.authn.online; import java.time.Duration; import java.time.LocalTime; +import java.util.concurrent.TimeUnit; -import org.ehcache.UserManagedCache; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.UserManagedCacheBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + public class InMemoryOnlineTicketServices implements OnlineTicketServices{ private static final Logger _logger = LoggerFactory.getLogger(InMemoryOnlineTicketServices.class); - - protected static UserManagedCache onlineTicketStore = - UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, OnlineTicket.class) - .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(30))) - .build(true); + protected static Cache onlineTicketStore = + Caffeine.newBuilder() + .expireAfterWrite(30, TimeUnit.MINUTES) + .maximumSize(200000) + .build(); public InMemoryOnlineTicketServices() { super(); @@ -47,27 +48,24 @@ public class InMemoryOnlineTicketServices implements OnlineTicketServices{ @Override public OnlineTicket remove(String ticketId) { - OnlineTicket ticket=onlineTicketStore.get(ticketId); - onlineTicketStore.remove(ticketId); + OnlineTicket ticket=onlineTicketStore.getIfPresent(ticketId); + onlineTicketStore.invalidate(ticketId); return ticket; } @Override public OnlineTicket get(String ticketId) { - OnlineTicket ticket=onlineTicketStore.get(ticketId); + OnlineTicket ticket=onlineTicketStore.getIfPresent(ticketId); return ticket; } @Override public void setValiditySeconds(int validitySeconds) { onlineTicketStore = - UserManagedCacheBuilder. - newUserManagedCacheBuilder(String.class, OnlineTicket.class) - .withExpiry( - ExpiryPolicyBuilder.timeToLiveExpiration( - Duration.ofMinutes(validitySeconds/60)) - ) - .build(true); + Caffeine.newBuilder() + .expireAfterWrite(validitySeconds/60, TimeUnit.MINUTES) + .maximumSize(200000) + .build(); } diff --git a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/support/rememberme/InMemoryRemeberMeService.java b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/support/rememberme/InMemoryRemeberMeService.java index 5bfd2d213..b31f4fd76 100644 --- a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/support/rememberme/InMemoryRemeberMeService.java +++ b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/support/rememberme/InMemoryRemeberMeService.java @@ -17,22 +17,19 @@ package org.maxkey.authn.support.rememberme; -import java.time.Duration; -import org.ehcache.UserManagedCache; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.UserManagedCacheBuilder; +import java.util.concurrent.TimeUnit; + import org.maxkey.constants.ConstantsTimeInterval; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + public class InMemoryRemeberMeService extends AbstractRemeberMeService { - protected static final UserManagedCache remeberMeStore = - UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, RemeberMe.class) - .withExpiry( - ExpiryPolicyBuilder.timeToLiveExpiration( - Duration.ofMinutes(ConstantsTimeInterval.TWO_WEEK) - ) - ) - .build(true); + protected static final Cache remeberMeStore = + Caffeine.newBuilder() + .expireAfterWrite(ConstantsTimeInterval.TWO_WEEK, TimeUnit.MINUTES) + .build(); @Override public void save(RemeberMe remeberMe) { @@ -46,12 +43,12 @@ public class InMemoryRemeberMeService extends AbstractRemeberMeService { @Override public RemeberMe read(RemeberMe remeberMe) { - return remeberMeStore.get(remeberMe.getUsername()); + return remeberMeStore.getIfPresent(remeberMe.getUsername()); } @Override public void remove(String username) { - remeberMeStore.remove(username); + remeberMeStore.invalidate(username); } } diff --git a/maxkey-authentications/maxkey-authentication-otp/src/main/java/org/maxkey/password/onetimepwd/token/InMemoryOtpTokenStore.java b/maxkey-authentications/maxkey-authentication-otp/src/main/java/org/maxkey/password/onetimepwd/token/InMemoryOtpTokenStore.java index 5a836ac26..ff57b63be 100644 --- a/maxkey-authentications/maxkey-authentication-otp/src/main/java/org/maxkey/password/onetimepwd/token/InMemoryOtpTokenStore.java +++ b/maxkey-authentications/maxkey-authentication-otp/src/main/java/org/maxkey/password/onetimepwd/token/InMemoryOtpTokenStore.java @@ -17,29 +17,26 @@ package org.maxkey.password.onetimepwd.token; -import org.ehcache.UserManagedCache; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.UserManagedCacheBuilder; +import java.util.concurrent.TimeUnit; + import org.joda.time.DateTime; import org.joda.time.Duration; import org.joda.time.format.DateTimeFormat; -import org.maxkey.constants.ConstantsTimeInterval; import org.maxkey.entity.UserInfo; import org.maxkey.password.onetimepwd.OneTimePassword; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + public class InMemoryOtpTokenStore extends AbstractOtpTokenStore { private static final Logger logger = LoggerFactory.getLogger(InMemoryOtpTokenStore.class); - protected static final UserManagedCache optTokenStore = - UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, OneTimePassword.class) - .withExpiry( - ExpiryPolicyBuilder.timeToLiveExpiration( - java.time.Duration.ofMinutes(ConstantsTimeInterval.ONE_MINUTE * 5) - ) - ) - .build(true); + protected static final Cache optTokenStore = + Caffeine.newBuilder() + .expireAfterWrite(5, TimeUnit.MINUTES) + .build(); @Override public void store(UserInfo userInfo, String token, String receiver, String type) { @@ -57,7 +54,7 @@ public class InMemoryOtpTokenStore extends AbstractOtpTokenStore { @Override public boolean validate(UserInfo userInfo, String token, String type, int interval) { - OneTimePassword otp = optTokenStore.get(userInfo.getUsername() + "_" + type + "_" + token); + OneTimePassword otp = optTokenStore.getIfPresent(userInfo.getUsername() + "_" + type + "_" + token); if (otp != null) { DateTime currentdateTime = new DateTime(); DateTime oneCreateTime = DateTime.parse(otp.getCreateTime(), diff --git a/maxkey-core/src/main/java/org/maxkey/persistence/db/PasswordPolicyValidator.java b/maxkey-core/src/main/java/org/maxkey/persistence/db/PasswordPolicyValidator.java index 4d624a42d..81adb9dff 100644 --- a/maxkey-core/src/main/java/org/maxkey/persistence/db/PasswordPolicyValidator.java +++ b/maxkey-core/src/main/java/org/maxkey/persistence/db/PasswordPolicyValidator.java @@ -23,17 +23,14 @@ import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; import java.util.Date; +import java.util.concurrent.TimeUnit; -import org.ehcache.UserManagedCache; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.UserManagedCacheBuilder; import org.joda.time.DateTime; import org.joda.time.Duration; import org.joda.time.format.DateTimeFormat; import org.maxkey.constants.ConstantsPasswordSetType; import org.maxkey.constants.ConstantsProperties; import org.maxkey.constants.ConstantsStatus; -import org.maxkey.constants.ConstantsTimeInterval; import org.maxkey.crypto.password.PasswordGen; import org.maxkey.entity.PasswordPolicy; import org.maxkey.entity.UserInfo; @@ -63,6 +60,9 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.security.authentication.BadCredentialsException; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + public class PasswordPolicyValidator { private static Logger _logger = LoggerFactory.getLogger(PasswordPolicyValidator.class); @@ -71,14 +71,10 @@ public class PasswordPolicyValidator { "classpath:/top_weak_password.txt"; //Cache PasswordPolicy in memory ONE_HOUR - protected static final UserManagedCache passwordPolicyStore = - UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, PasswordPolicy.class) - .withExpiry( - ExpiryPolicyBuilder.timeToLiveExpiration( - java.time.Duration.ofMinutes(ConstantsTimeInterval.ONE_HOUR) - ) - ) - .build(true); + protected static final Cache passwordPolicyStore = + Caffeine.newBuilder() + .expireAfterWrite(60, TimeUnit.MINUTES) + .build(); protected PasswordPolicy passwordPolicy; @@ -115,7 +111,7 @@ public class PasswordPolicyValidator { * @return */ public PasswordPolicy getPasswordPolicy() { - passwordPolicy = passwordPolicyStore.get(PASSWORD_POLICY_KEY); + passwordPolicy = passwordPolicyStore.getIfPresent(PASSWORD_POLICY_KEY); if (passwordPolicy == null) { passwordPolicy = jdbcTemplate.queryForObject(PASSWORD_POLICY_SELECT_STATEMENT, diff --git a/maxkey-lib/mybatis-jpa-extra-2.5.jar b/maxkey-lib/mybatis-jpa-extra-2.5.jar deleted file mode 100644 index 313de54c8..000000000 Binary files a/maxkey-lib/mybatis-jpa-extra-2.5.jar and /dev/null differ diff --git a/maxkey-lib/mybatis-jpa-extra-2.6.jar b/maxkey-lib/mybatis-jpa-extra-2.6.jar new file mode 100644 index 000000000..a163dd64e Binary files /dev/null and b/maxkey-lib/mybatis-jpa-extra-2.6.jar differ diff --git a/maxkey-lib/mybatis-jpa-extra-spring-boot-starter-2.5.jar b/maxkey-lib/mybatis-jpa-extra-spring-boot-starter-2.6.jar similarity index 84% rename from maxkey-lib/mybatis-jpa-extra-spring-boot-starter-2.5.jar rename to maxkey-lib/mybatis-jpa-extra-spring-boot-starter-2.6.jar index 464e92251..56723d433 100644 Binary files a/maxkey-lib/mybatis-jpa-extra-spring-boot-starter-2.5.jar and b/maxkey-lib/mybatis-jpa-extra-spring-boot-starter-2.6.jar differ diff --git a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/AppsService.java b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/AppsService.java index f113e86e9..8f9a7ee45 100644 --- a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/AppsService.java +++ b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/AppsService.java @@ -17,29 +17,25 @@ package org.maxkey.persistence.service; -import java.time.Duration; import java.util.List; +import java.util.concurrent.TimeUnit; import org.apache.mybatis.jpa.persistence.JpaBaseService; -import org.ehcache.UserManagedCache; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.UserManagedCacheBuilder; import org.maxkey.entity.apps.Apps; import org.maxkey.entity.apps.UserApps; import org.maxkey.persistence.mapper.AppsMapper; import org.springframework.stereotype.Repository; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + @Repository public class AppsService extends JpaBaseService{ - protected final static UserManagedCache appsDetailsCacheStore = - UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, Apps.class) - .withExpiry( - ExpiryPolicyBuilder.timeToLiveExpiration( - Duration.ofHours(1) - ) - ) - .build(true); + protected final static Cache appsDetailsCacheStore = + Caffeine.newBuilder() + .expireAfterWrite(60, TimeUnit.MINUTES) + .build(); public AppsService() { super(AppsMapper.class); @@ -50,7 +46,6 @@ public class AppsService extends JpaBaseService{ */ @Override public AppsMapper getMapper() { - // TODO Auto-generated method stub return (AppsMapper)super.getMapper(); } @@ -75,7 +70,7 @@ public class AppsService extends JpaBaseService{ } public Apps getCacheAppDetails(String appId) { - Apps appDetails=appsDetailsCacheStore.get(appId); + Apps appDetails=appsDetailsCacheStore.getIfPresent(appId); return appDetails; } } diff --git a/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/pgt/InMemoryProxyGrantingTicketServices.java b/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/pgt/InMemoryProxyGrantingTicketServices.java index 81f9ab92d..ad486b01c 100644 --- a/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/pgt/InMemoryProxyGrantingTicketServices.java +++ b/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/pgt/InMemoryProxyGrantingTicketServices.java @@ -17,21 +17,21 @@ package org.maxkey.authz.cas.endpoint.ticket.pgt; -import java.time.Duration; +import java.util.concurrent.TimeUnit; -import org.ehcache.UserManagedCache; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.UserManagedCacheBuilder; import org.maxkey.authz.cas.endpoint.ticket.RandomServiceTicketServices; import org.maxkey.authz.cas.endpoint.ticket.Ticket; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + public class InMemoryProxyGrantingTicketServices extends RandomServiceTicketServices { - protected final static UserManagedCache casTicketStore = - UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, Ticket.class) - .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofHours(1))) - .build(true); + protected final static Cache casTicketStore = + Caffeine.newBuilder() + .expireAfterWrite(60, TimeUnit.MINUTES) + .build(); @Override @@ -41,15 +41,15 @@ public class InMemoryProxyGrantingTicketServices extends RandomServiceTicketServ @Override public Ticket remove(String ticketId) { - Ticket ticket=casTicketStore.get(ticketId); - casTicketStore.remove(ticketId); + Ticket ticket=casTicketStore.getIfPresent(ticketId); + casTicketStore.invalidate(ticketId); return ticket; } @Override public Ticket get(String ticket) { // TODO Auto-generated method stub - return casTicketStore.get(ticket); + return casTicketStore.getIfPresent(ticket); } } diff --git a/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/st/InMemoryTicketServices.java b/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/st/InMemoryTicketServices.java index 7c6cbe5e3..026836cb4 100644 --- a/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/st/InMemoryTicketServices.java +++ b/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/st/InMemoryTicketServices.java @@ -17,21 +17,21 @@ package org.maxkey.authz.cas.endpoint.ticket.st; -import java.time.Duration; +import java.util.concurrent.TimeUnit; -import org.ehcache.UserManagedCache; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.UserManagedCacheBuilder; import org.maxkey.authz.cas.endpoint.ticket.RandomServiceTicketServices; import org.maxkey.authz.cas.endpoint.ticket.Ticket; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + public class InMemoryTicketServices extends RandomServiceTicketServices { - protected final static UserManagedCache casTicketStore = - UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, Ticket.class) - .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(60))) - .build(true); + protected final static Cache casTicketStore = + Caffeine.newBuilder() + .expireAfterWrite(60, TimeUnit.MINUTES) + .build(); @Override @@ -41,8 +41,8 @@ public class InMemoryTicketServices extends RandomServiceTicketServices { @Override public Ticket remove(String ticketId) { - Ticket ticket=casTicketStore.get(ticketId); - casTicketStore.remove(ticketId); + Ticket ticket=casTicketStore.getIfPresent(ticketId); + casTicketStore.invalidate(ticketId); return ticket; } diff --git a/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/tgt/InMemoryTicketGrantingTicketServices.java b/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/tgt/InMemoryTicketGrantingTicketServices.java index 4d20a6c89..991aa60ca 100644 --- a/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/tgt/InMemoryTicketGrantingTicketServices.java +++ b/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/tgt/InMemoryTicketGrantingTicketServices.java @@ -17,22 +17,21 @@ package org.maxkey.authz.cas.endpoint.ticket.tgt; -import java.time.Duration; +import java.util.concurrent.TimeUnit; -import org.ehcache.UserManagedCache; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.UserManagedCacheBuilder; import org.maxkey.authz.cas.endpoint.ticket.RandomServiceTicketServices; import org.maxkey.authz.cas.endpoint.ticket.Ticket; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + public class InMemoryTicketGrantingTicketServices extends RandomServiceTicketServices { - protected final static UserManagedCache casTicketGrantingTicketStore = - UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, Ticket.class) - .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofDays(2))) - .build(true); - + protected final static Cache casTicketGrantingTicketStore = + Caffeine.newBuilder() + .expireAfterWrite(2, TimeUnit.DAYS) + .build(); @Override public void store(String ticketId, Ticket ticket) { @@ -41,14 +40,14 @@ public class InMemoryTicketGrantingTicketServices extends RandomServiceTicketSer @Override public Ticket remove(String ticketId) { - Ticket ticket=casTicketGrantingTicketStore.get(ticketId); - casTicketGrantingTicketStore.remove(ticketId); + Ticket ticket=casTicketGrantingTicketStore.getIfPresent(ticketId); + casTicketGrantingTicketStore.invalidate(ticketId); return ticket; } @Override public Ticket get(String ticketId) { - Ticket ticket=casTicketGrantingTicketStore.get(ticketId); + Ticket ticket=casTicketGrantingTicketStore.getIfPresent(ticketId); return ticket; } diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/common/util/OAuth2Utils.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/common/util/OAuth2Utils.java index bad5fde63..c78737559 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/common/util/OAuth2Utils.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/common/util/OAuth2Utils.java @@ -32,46 +32,6 @@ import org.springframework.util.StringUtils; */ public abstract class OAuth2Utils { - /** - * Constant to use while parsing and formatting parameter maps for OAuth2 requests - */ - public static final String CLIENT_ID = "client_id"; - - /** - * Constant to use while parsing and formatting parameter maps for OAuth2 requests - */ - public static final String STATE = "state"; - - /** - * Constant to use while parsing and formatting parameter maps for OAuth2 requests - */ - public static final String SCOPE = "scope"; - - /** - * Constant to use while parsing and formatting parameter maps for OAuth2 requests - */ - public static final String REDIRECT_URI = "redirect_uri"; - - /** - * Constant to use while parsing and formatting parameter maps for OAuth2 requests - */ - public static final String RESPONSE_TYPE = "response_type"; - - /** - * Constant to use while parsing and formatting parameter maps for OAuth2 requests - */ - public static final String USER_OAUTH_APPROVAL = "user_oauth_approval"; - - /** - * Constant to use as a prefix for scope approval - */ - public static final String SCOPE_PREFIX = "scope."; - - /** - * Constant to use while parsing and formatting parameter maps for OAuth2 requests - */ - public static final String GRANT_TYPE = "grant_type"; - /** * Parses a string parameter value into a set of strings. * diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/OAuth2Request.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/OAuth2Request.java index 7ba05381c..d1e284183 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/OAuth2Request.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/OAuth2Request.java @@ -24,7 +24,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.maxkey.authz.oauth2.common.util.OAuth2Utils; +import org.maxkey.authz.oauth2.common.OAuth2Constants; import org.springframework.security.core.GrantedAuthority; /** @@ -228,11 +228,11 @@ public class OAuth2Request extends BaseRequest implements Serializable { * @return the grant type if known, or null otherwise */ public String getGrantType() { - if (getRequestParameters().containsKey(OAuth2Utils.GRANT_TYPE)) { - return getRequestParameters().get(OAuth2Utils.GRANT_TYPE); + if (getRequestParameters().containsKey(OAuth2Constants.PARAMETER.GRANT_TYPE)) { + return getRequestParameters().get(OAuth2Constants.PARAMETER.GRANT_TYPE); } - if (getRequestParameters().containsKey(OAuth2Utils.RESPONSE_TYPE)) { - String response = getRequestParameters().get(OAuth2Utils.RESPONSE_TYPE); + if (getRequestParameters().containsKey(OAuth2Constants.PARAMETER.RESPONSE_TYPE)) { + String response = getRequestParameters().get(OAuth2Constants.PARAMETER.RESPONSE_TYPE); if (response.contains("token")) { return "implicit"; } diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/OAuth2RequestValidator.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/OAuth2RequestValidator.java index 4dccd950f..3dacb09d3 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/OAuth2RequestValidator.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/OAuth2RequestValidator.java @@ -18,7 +18,6 @@ package org.maxkey.authz.oauth2.provider; import org.maxkey.authz.oauth2.common.exceptions.InvalidScopeException; -import org.maxkey.authz.oauth2.provider.endpoint.AuthorizationEndpoint; import org.maxkey.authz.oauth2.provider.endpoint.TokenEndpoint; import org.maxkey.entity.apps.oauth2.provider.ClientDetails; diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java index 1e5ef6b37..76fdd35fb 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java @@ -27,6 +27,7 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.maxkey.authz.oauth2.common.OAuth2Constants; import org.maxkey.authz.oauth2.common.util.OAuth2Utils; import org.maxkey.authz.oauth2.provider.AuthorizationRequest; import org.maxkey.authz.oauth2.provider.ClientDetailsService; @@ -48,7 +49,7 @@ public class ApprovalStoreUserApprovalHandler implements UserApprovalHandler, In private static Log logger = LogFactory.getLog(ApprovalStoreUserApprovalHandler.class); - private String scopePrefix = OAuth2Utils.SCOPE_PREFIX; + private String scopePrefix = OAuth2Constants.PARAMETER.SCOPE_PREFIX; private ApprovalStore approvalStore; @@ -232,12 +233,12 @@ public class ApprovalStoreUserApprovalHandler implements UserApprovalHandler, In model.putAll(authorizationRequest.getRequestParameters()); Map scopes = new LinkedHashMap(); for (String scope : authorizationRequest.getScope()) { - scopes.put(OAuth2Utils.SCOPE_PREFIX + scope, "false"); + scopes.put(OAuth2Constants.PARAMETER.SCOPE_PREFIX + scope, "false"); } for (Approval approval : approvalStore.getApprovals(userAuthentication.getName(), authorizationRequest.getClientId())) { if (authorizationRequest.getScope().contains(approval.getScope())) { - scopes.put(OAuth2Utils.SCOPE_PREFIX + approval.getScope(), + scopes.put(OAuth2Constants.PARAMETER.SCOPE_PREFIX + approval.getScope(), approval.getStatus() == ApprovalStatus.APPROVED ? "true" : "false"); } } diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/DefaultUserApprovalHandler.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/DefaultUserApprovalHandler.java index 5993109b3..7803983b9 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/DefaultUserApprovalHandler.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/DefaultUserApprovalHandler.java @@ -19,7 +19,7 @@ package org.maxkey.authz.oauth2.provider.approval; import java.util.HashMap; import java.util.Map; -import org.maxkey.authz.oauth2.common.util.OAuth2Utils; +import org.maxkey.authz.oauth2.common.OAuth2Constants; import org.maxkey.authz.oauth2.provider.AuthorizationRequest; import org.springframework.security.core.Authentication; @@ -31,7 +31,7 @@ import org.springframework.security.core.Authentication; */ public class DefaultUserApprovalHandler implements UserApprovalHandler { - private String approvalParameter = OAuth2Utils.USER_OAUTH_APPROVAL; + private String approvalParameter = OAuth2Constants.PARAMETER.USER_OAUTH_APPROVAL; /** * @param approvalParameter the approvalParameter to set diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/TokenStoreUserApprovalHandler.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/TokenStoreUserApprovalHandler.java index 2521f0c8c..7c543ab4a 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/TokenStoreUserApprovalHandler.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/TokenStoreUserApprovalHandler.java @@ -23,7 +23,7 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.maxkey.authz.oauth2.common.OAuth2AccessToken; -import org.maxkey.authz.oauth2.common.util.OAuth2Utils; +import org.maxkey.authz.oauth2.common.OAuth2Constants; import org.maxkey.authz.oauth2.provider.AuthorizationRequest; import org.maxkey.authz.oauth2.provider.ClientDetailsService; import org.maxkey.authz.oauth2.provider.ClientRegistrationException; @@ -46,7 +46,7 @@ public class TokenStoreUserApprovalHandler implements UserApprovalHandler, Initi private static Log logger = LogFactory.getLog(TokenStoreUserApprovalHandler.class); - private String approvalParameter = OAuth2Utils.USER_OAUTH_APPROVAL; + private String approvalParameter = OAuth2Constants.PARAMETER.USER_OAUTH_APPROVAL; private TokenStore tokenStore; diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/endpoint/OAuth20AccessConfirmationEndpoint.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/endpoint/OAuth20AccessConfirmationEndpoint.java index 033fef794..e3c016821 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/endpoint/OAuth20AccessConfirmationEndpoint.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/approval/endpoint/OAuth20AccessConfirmationEndpoint.java @@ -21,7 +21,6 @@ import java.util.LinkedHashMap; import java.util.Map; import org.maxkey.authn.SigninPrincipal; import org.maxkey.authz.oauth2.common.OAuth2Constants; -import org.maxkey.authz.oauth2.common.util.OAuth2Utils; import org.maxkey.authz.oauth2.provider.AuthorizationRequest; import org.maxkey.authz.oauth2.provider.ClientDetailsService; import org.maxkey.authz.oauth2.provider.approval.Approval; @@ -99,13 +98,13 @@ public class OAuth20AccessConfirmationEndpoint { model.put("oauth_version", "oauth 2.0"); Map scopes = new LinkedHashMap(); for (String scope : clientAuth.getScope()) { - scopes.put(OAuth2Utils.SCOPE_PREFIX + scope, "false"); + scopes.put(OAuth2Constants.PARAMETER.SCOPE_PREFIX + scope, "false"); } String principal = ((SigninPrincipal) WebContext.getAuthentication().getPrincipal()).getUsername(); for (Approval approval : approvalStore.getApprovals(principal, client.getClientId())) { if (clientAuth.getScope().contains(approval.getScope())) { - scopes.put(OAuth2Utils.SCOPE_PREFIX + approval.getScope(), + scopes.put(OAuth2Constants.PARAMETER.SCOPE_PREFIX + approval.getScope(), approval.getStatus() == ApprovalStatus.APPROVED ? "true" : "false"); } } diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/client/InMemoryClientDetailsService.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/client/InMemoryClientDetailsService.java deleted file mode 100644 index fad750647..000000000 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/client/InMemoryClientDetailsService.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2008 Web Cohesion - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.maxkey.authz.oauth2.provider.client; - -import java.util.HashMap; -import java.util.Map; - -import org.maxkey.authz.oauth2.provider.ClientDetailsService; -import org.maxkey.authz.oauth2.provider.ClientRegistrationException; -import org.maxkey.authz.oauth2.provider.NoSuchClientException; -import org.maxkey.entity.apps.oauth2.provider.ClientDetails; - -/** - * Basic, in-memory implementation of the client details service. - * - * @author Ryan Heaton - */ -public class InMemoryClientDetailsService implements ClientDetailsService { - - private Map clientDetailsStore = new HashMap(); - - public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { - ClientDetails details = clientDetailsStore.get(clientId); - if (details == null) { - throw new NoSuchClientException("No client with requested id: " + clientId); - } - return details; - } - - public void setClientDetailsStore(Map clientDetailsStore) { - this.clientDetailsStore = new HashMap(clientDetailsStore); - } - -} \ No newline at end of file diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/client/JdbcClientDetailsService.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/client/JdbcClientDetailsService.java index 8f1b80e18..6e6158fc5 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/client/JdbcClientDetailsService.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/client/JdbcClientDetailsService.java @@ -23,6 +23,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; import javax.sql.DataSource; @@ -47,12 +48,21 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + /** * Basic, JDBC implementation of the client details service. */ public class JdbcClientDetailsService implements ClientDetailsService, ClientRegistrationService{ private static final Log logger = LogFactory.getLog(JdbcClientDetailsService.class); + + protected final static Cache clientDetailsCache = + Caffeine.newBuilder() + .expireAfterWrite(60, TimeUnit.MINUTES) + .maximumSize(200000) + .build(); private JsonMapper mapper = createJsonMapper(); @@ -116,13 +126,16 @@ public class JdbcClientDetailsService implements ClientDetailsService, ClientReg } public ClientDetails loadClientByClientId(String clientId) { - ClientDetails details; - try { - details = jdbcTemplate.queryForObject(selectClientDetailsSql, new ClientDetailsRowMapper(), clientId); - } catch (EmptyResultDataAccessException e) { - throw new NoSuchClientException("No client with requested id: " + clientId); + //TODO: cache in memory + ClientDetails details = clientDetailsCache.getIfPresent(clientId); + if(details == null) { + try { + details = jdbcTemplate.queryForObject(selectClientDetailsSql, new ClientDetailsRowMapper(), clientId); + clientDetailsCache.put(clientId, details); + } catch (EmptyResultDataAccessException e) { + throw new NoSuchClientException("No client with requested id: " + clientId); + } } - return details; } diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/code/InMemoryAuthorizationCodeServices.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/code/InMemoryAuthorizationCodeServices.java index 26836af2f..dd91cdf3b 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/code/InMemoryAuthorizationCodeServices.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/code/InMemoryAuthorizationCodeServices.java @@ -17,12 +17,11 @@ package org.maxkey.authz.oauth2.provider.code; -import java.time.Duration; +import java.util.concurrent.TimeUnit; -import org.ehcache.UserManagedCache; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.UserManagedCacheBuilder; import org.maxkey.authz.oauth2.provider.OAuth2Authentication; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; /** * Implementation of authorization code services that stores the codes and authentication in memory. @@ -31,10 +30,10 @@ import org.maxkey.authz.oauth2.provider.OAuth2Authentication; * @author Dave Syer */ public class InMemoryAuthorizationCodeServices extends RandomValueAuthorizationCodeServices { - protected final static UserManagedCache authorizationCodeStore = - UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, OAuth2Authentication.class) - .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(60))) - .build(true); + protected final static Cache authorizationCodeStore = + Caffeine.newBuilder() + .expireAfterWrite(3, TimeUnit.MINUTES) + .build(); @Override protected void store(String code, OAuth2Authentication authentication) { authorizationCodeStore.put(code, authentication); @@ -42,8 +41,8 @@ public class InMemoryAuthorizationCodeServices extends RandomValueAuthorizationC @Override public OAuth2Authentication remove(String code) { - OAuth2Authentication auth = authorizationCodeStore.get(code); - authorizationCodeStore.remove(code); + OAuth2Authentication auth = authorizationCodeStore.getIfPresent(code); + authorizationCodeStore.invalidate(code); return auth; } diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/code/JdbcAuthorizationCodeServices.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/code/JdbcAuthorizationCodeServices.java deleted file mode 100644 index f70747baf..000000000 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/code/JdbcAuthorizationCodeServices.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright [2020] [MaxKey of copyright http://www.maxkey.top] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.maxkey.authz.oauth2.provider.code; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; - -import javax.sql.DataSource; - -import org.maxkey.authz.oauth2.provider.OAuth2Authentication; -import org.maxkey.util.SerializationUtils; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.support.SqlLobValue; -import org.springframework.util.Assert; - -/** - * Implementation of authorization code services that stores the codes and - * authentication in a database. - * - * @author Crystal.Sea - */ -public class JdbcAuthorizationCodeServices extends RandomValueAuthorizationCodeServices { - - private static final String DEFAULT_SELECT_STATEMENT = "select code, authentication from oauth_code where code = ?"; - private static final String DEFAULT_INSERT_STATEMENT = "insert into oauth_code (code, authentication) values (?, ?)"; - private static final String DEFAULT_DELETE_STATEMENT = "delete from oauth_code where code = ?"; - - private String selectAuthenticationSql = DEFAULT_SELECT_STATEMENT; - private String insertAuthenticationSql = DEFAULT_INSERT_STATEMENT; - private String deleteAuthenticationSql = DEFAULT_DELETE_STATEMENT; - - private final JdbcTemplate jdbcTemplate; - - public JdbcAuthorizationCodeServices(DataSource dataSource) { - Assert.notNull(dataSource, "DataSource required"); - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - public JdbcAuthorizationCodeServices(JdbcTemplate jdbcTemplate) { - Assert.notNull(jdbcTemplate, "jdbcTemplate required"); - this.jdbcTemplate = jdbcTemplate; - } - - @Override - protected void store(String code, OAuth2Authentication authentication) { - jdbcTemplate.update(insertAuthenticationSql, - new Object[] { code, new SqlLobValue(SerializationUtils.serialize(authentication)) }, - new int[] { Types.VARCHAR, Types.BLOB }); - } - - public OAuth2Authentication remove(String code) { - OAuth2Authentication authentication; - - try { - authentication = jdbcTemplate.queryForObject(selectAuthenticationSql, - new RowMapper() { - public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException { - return SerializationUtils.deserialize(rs.getBytes("authentication")); - } - }, code); - } catch (EmptyResultDataAccessException e) { - return null; - } - - if (authentication != null) { - jdbcTemplate.update(deleteAuthenticationSql, code); - } - - return authentication; - } - - public void setSelectAuthenticationSql(String selectAuthenticationSql) { - this.selectAuthenticationSql = selectAuthenticationSql; - } - - public void setInsertAuthenticationSql(String insertAuthenticationSql) { - this.insertAuthenticationSql = insertAuthenticationSql; - } - - public void setDeleteAuthenticationSql(String deleteAuthenticationSql) { - this.deleteAuthenticationSql = deleteAuthenticationSql; - } -} diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/AbstractEndpoint.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/AbstractEndpoint.java index 2c9221f2c..e6decbdfa 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/AbstractEndpoint.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/AbstractEndpoint.java @@ -34,6 +34,7 @@ import org.maxkey.authz.oauth2.provider.password.ResourceOwnerPasswordTokenGrant import org.maxkey.authz.oauth2.provider.refresh.RefreshTokenGranter; import org.maxkey.authz.oauth2.provider.request.DefaultOAuth2RequestFactory; import org.maxkey.authz.oauth2.provider.token.AuthorizationServerTokenServices; +import org.maxkey.configuration.ApplicationConfig; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -56,23 +57,28 @@ public class AbstractEndpoint implements InitializingBean { @Autowired @Qualifier("oauth20TokenServices") - AuthorizationServerTokenServices tokenServices ; + protected AuthorizationServerTokenServices tokenServices ; @Autowired @Qualifier("oauth20JdbcClientDetailsService") - private ClientDetailsService clientDetailsService; - @Autowired - @Qualifier("oAuth2RequestFactory") - private OAuth2RequestFactory oAuth2RequestFactory; + protected ClientDetailsService clientDetailsService; @Autowired @Qualifier("oAuth2RequestFactory") - private OAuth2RequestFactory defaultOAuth2RequestFactory; + protected OAuth2RequestFactory oAuth2RequestFactory; + + @Autowired + @Qualifier("oAuth2RequestFactory") + protected OAuth2RequestFactory defaultOAuth2RequestFactory; @Autowired @Qualifier("oauth20UserAuthenticationManager") AuthenticationManager authenticationManager; + @Autowired + @Qualifier("applicationConfig") + protected ApplicationConfig applicationConfig; + public void afterPropertiesSet() throws Exception { if (tokenGranter == null) { diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/AuthorizationEndpoint.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/AuthorizationEndpoint.java index e2f871602..00511c7d1 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -43,13 +43,10 @@ import org.maxkey.authz.oauth2.provider.code.AuthorizationCodeServices; import org.maxkey.authz.oauth2.provider.implicit.ImplicitTokenRequest; import org.maxkey.authz.oauth2.provider.request.DefaultOAuth2RequestValidator; import org.maxkey.util.HttpEncoder; -import org.maxkey.configuration.ApplicationConfig; import org.maxkey.entity.apps.oauth2.provider.ClientDetails; import org.maxkey.web.WebContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -69,7 +66,6 @@ import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriTemplate; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; -import org.maxkey.authz.oauth2.provider.ClientDetailsService; /** *

@@ -96,14 +92,6 @@ public class AuthorizationEndpoint extends AbstractEndpoint { private static final String OAUTH_V20_AUTHORIZATION_URL = "%s" + OAuth2Constants.ENDPOINT.ENDPOINT_AUTHORIZE + "?client_id=%s&response_type=code&redirect_uri=%s&approval_prompt=auto"; - @Autowired - @Qualifier("oauth20JdbcClientDetailsService") - private ClientDetailsService clientDetailsService; - - @Autowired - @Qualifier("applicationConfig") - protected ApplicationConfig applicationConfig; - private RedirectResolver redirectResolver = new DefaultRedirectResolver(); private UserApprovalHandler userApprovalHandler = new DefaultUserApprovalHandler(); @@ -121,6 +109,30 @@ public class AuthorizationEndpoint extends AbstractEndpoint { this.errorPage = errorPage; } + @ApiOperation(value = "OAuth 2.0 认证接口", notes = "传递参数应用ID,自动完成跳转认证拼接",httpMethod="GET") + @RequestMapping(OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/{id}") + public ModelAndView authorize( + HttpServletRequest request, + HttpServletResponse response, + @PathVariable("id") String id){ + ClientDetails clientDetails =getClientDetailsService().loadClientByClientId(id); + _logger.debug(""+clientDetails); + String authorizationUrl = ""; + try { + authorizationUrl = String.format(OAUTH_V20_AUTHORIZATION_URL, + applicationConfig.getServerPrefix(), + clientDetails.getClientId(), + HttpEncoder.encode(clientDetails.getRegisteredRedirectUri().toArray()[0].toString()) + ); + } catch (Exception e) { + e.printStackTrace(); + } + + _logger.debug("authorizationUrl "+authorizationUrl); + + return WebContext.redirect(authorizationUrl); + } + @ApiOperation(value = "OAuth 2.0 认证接口", notes = "传递参数client_id,response_type,redirect_uri等",httpMethod="GET") @RequestMapping(value = OAuth2Constants.ENDPOINT.ENDPOINT_AUTHORIZE, method = RequestMethod.GET) public ModelAndView authorize( @@ -204,7 +216,8 @@ public class AuthorizationEndpoint extends AbstractEndpoint { } - @RequestMapping(value = OAuth2Constants.ENDPOINT.ENDPOINT_AUTHORIZE, method = RequestMethod.POST, params = OAuth2Utils.USER_OAUTH_APPROVAL) + //approval must post + @RequestMapping(value = OAuth2Constants.ENDPOINT.ENDPOINT_AUTHORIZE, method = RequestMethod.POST, params = OAuth2Constants.PARAMETER.USER_OAUTH_APPROVAL) public View approveOrDeny( @RequestParam Map approvalParameters, Map model, @@ -529,28 +542,4 @@ public class AuthorizationEndpoint extends AbstractEndpoint { this.oauth2RequestValidator = oauth2RequestValidator; } - @ApiOperation(value = "OAuth 2.0 认证接口", notes = "传递参数应用ID,自动完成跳转认证拼接",httpMethod="GET") - @RequestMapping(OAuth2Constants.ENDPOINT.ENDPOINT_BASE + "/{id}") - public ModelAndView authorize( - HttpServletRequest request, - HttpServletResponse response, - @PathVariable("id") String id){ - ClientDetails clientDetails =clientDetailsService.loadClientByClientId(id); - _logger.debug(""+clientDetails); - String authorizationUrl = ""; - try { - authorizationUrl = String.format(OAUTH_V20_AUTHORIZATION_URL, - applicationConfig.getServerPrefix(), - clientDetails.getClientId(), - HttpEncoder.encode(clientDetails.getRegisteredRedirectUri().toArray()[0].toString()) - ); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - _logger.debug("authorizationUrl "+authorizationUrl); - - return WebContext.redirect(authorizationUrl); - } } diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java index d4093e625..d260b95c2 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java @@ -210,7 +210,7 @@ public class TokenEndpointAuthenticationFilter implements Filter { } Map map = getSingleValueMap(request); - map.put(OAuth2Utils.CLIENT_ID, clientAuth.getName()); + map.put(OAuth2Constants.PARAMETER.CLIENT_ID, clientAuth.getName()); AuthorizationRequest authorizationRequest = oAuth2RequestFactory.createAuthorizationRequest(map); authorizationRequest.setScope(getScope(request)); diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/request/DefaultOAuth2RequestFactory.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/request/DefaultOAuth2RequestFactory.java index 2d209b871..f91509df6 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/request/DefaultOAuth2RequestFactory.java +++ b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/request/DefaultOAuth2RequestFactory.java @@ -69,14 +69,14 @@ public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory { public AuthorizationRequest createAuthorizationRequest(Map authorizationParameters) { - String clientId = authorizationParameters.get(OAuth2Utils.CLIENT_ID); - String state = authorizationParameters.get(OAuth2Utils.STATE); - String redirectUri = authorizationParameters.get(OAuth2Utils.REDIRECT_URI); + String clientId = authorizationParameters.get(OAuth2Constants.PARAMETER.CLIENT_ID); + String state = authorizationParameters.get(OAuth2Constants.PARAMETER.STATE); + String redirectUri = authorizationParameters.get(OAuth2Constants.PARAMETER.REDIRECT_URI); //oauth 2.1 PKCE String codeChallenge = authorizationParameters.get(OAuth2Constants.PARAMETER.CODE_CHALLENGE); String codeChallengeMethod = authorizationParameters.get(OAuth2Constants.PARAMETER.CODE_CHALLENGE_METHOD); Set responseTypes = OAuth2Utils.parseParameterList(authorizationParameters - .get(OAuth2Utils.RESPONSE_TYPE)); + .get(OAuth2Constants.PARAMETER.RESPONSE_TYPE)); Set scopes = extractScopes(authorizationParameters, clientId); @@ -97,7 +97,7 @@ public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory { public TokenRequest createTokenRequest(Map requestParameters, ClientDetails authenticatedClient) { - String clientId = requestParameters.get(OAuth2Utils.CLIENT_ID); + String clientId = requestParameters.get(OAuth2Constants.PARAMETER.CLIENT_ID); if (clientId == null) { // if the clientId wasn't passed in in the map, we add pull it from the authenticated client object clientId = authenticatedClient.getClientId(); @@ -108,7 +108,7 @@ public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory { throw new InvalidClientException("Given client ID does not match authenticated client"); } } - String grantType = requestParameters.get(OAuth2Utils.GRANT_TYPE); + String grantType = requestParameters.get(OAuth2Constants.PARAMETER.GRANT_TYPE); Set scopes = extractScopes(requestParameters, clientId); TokenRequest tokenRequest = new TokenRequest(requestParameters, clientId, scopes, grantType); @@ -127,7 +127,7 @@ public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory { } private Set extractScopes(Map requestParameters, String clientId) { - Set scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Utils.SCOPE)); + Set scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Constants.PARAMETER.SCOPE)); ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); if ((scopes == null || scopes.isEmpty())) { diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/token/store/JdbcTokenStore.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/token/store/JdbcTokenStore.java deleted file mode 100644 index 83d06b42e..000000000 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/token/store/JdbcTokenStore.java +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright [2020] [MaxKey of copyright http://www.maxkey.top] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.maxkey.authz.oauth2.provider.token.store; - -import java.io.UnsupportedEncodingException; -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import javax.sql.DataSource; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.maxkey.authz.oauth2.common.OAuth2AccessToken; -import org.maxkey.authz.oauth2.common.OAuth2RefreshToken; -import org.maxkey.authz.oauth2.provider.OAuth2Authentication; -import org.maxkey.authz.oauth2.provider.token.AuthenticationKeyGenerator; -import org.maxkey.authz.oauth2.provider.token.DefaultAuthenticationKeyGenerator; -import org.maxkey.authz.oauth2.provider.token.TokenStore; -import org.maxkey.util.SerializationUtils; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.support.SqlLobValue; -import org.springframework.util.Assert; - -/** - * Implementation of token services that stores tokens in a database. - * - * @author Ken Dombeck - * @author Luke Taylor - * @author Dave Syer - */ -public class JdbcTokenStore implements TokenStore { - - private static final Log LOG = LogFactory.getLog(JdbcTokenStore.class); - - private static final String DEFAULT_ACCESS_TOKEN_INSERT_STATEMENT = "insert into oauth_access_token (token_id, token, authentication_id, user_name, client_id, authentication, refresh_token) values (?, ?, ?, ?, ?, ?, ?)"; - - private static final String DEFAULT_ACCESS_TOKEN_SELECT_STATEMENT = "select token_id, token from oauth_access_token where token_id = ?"; - - private static final String DEFAULT_ACCESS_TOKEN_AUTHENTICATION_SELECT_STATEMENT = "select token_id, authentication from oauth_access_token where token_id = ?"; - - private static final String DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT = "select token_id, token from oauth_access_token where authentication_id = ?"; - - private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ? and client_id = ?"; - - private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ?"; - - private static final String DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT = "select token_id, token from oauth_access_token where client_id = ?"; - - private static final String DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT = "delete from oauth_access_token where token_id = ?"; - - private static final String DEFAULT_ACCESS_TOKEN_DELETE_FROM_REFRESH_TOKEN_STATEMENT = "delete from oauth_access_token where refresh_token = ?"; - - private static final String DEFAULT_REFRESH_TOKEN_INSERT_STATEMENT = "insert into oauth_refresh_token (token_id, token, authentication) values (?, ?, ?)"; - - private static final String DEFAULT_REFRESH_TOKEN_SELECT_STATEMENT = "select token_id, token from oauth_refresh_token where token_id = ?"; - - private static final String DEFAULT_REFRESH_TOKEN_AUTHENTICATION_SELECT_STATEMENT = "select token_id, authentication from oauth_refresh_token where token_id = ?"; - - private static final String DEFAULT_REFRESH_TOKEN_DELETE_STATEMENT = "delete from oauth_refresh_token where token_id = ?"; - - private String insertAccessTokenSql = DEFAULT_ACCESS_TOKEN_INSERT_STATEMENT; - - private String selectAccessTokenSql = DEFAULT_ACCESS_TOKEN_SELECT_STATEMENT; - - private String selectAccessTokenAuthenticationSql = DEFAULT_ACCESS_TOKEN_AUTHENTICATION_SELECT_STATEMENT; - - private String selectAccessTokenFromAuthenticationSql = DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT; - - private String selectAccessTokensFromUserNameAndClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT; - - private String selectAccessTokensFromUserNameSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT; - - private String selectAccessTokensFromClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT; - - private String deleteAccessTokenSql = DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT; - - private String insertRefreshTokenSql = DEFAULT_REFRESH_TOKEN_INSERT_STATEMENT; - - private String selectRefreshTokenSql = DEFAULT_REFRESH_TOKEN_SELECT_STATEMENT; - - private String selectRefreshTokenAuthenticationSql = DEFAULT_REFRESH_TOKEN_AUTHENTICATION_SELECT_STATEMENT; - - private String deleteRefreshTokenSql = DEFAULT_REFRESH_TOKEN_DELETE_STATEMENT; - - private String deleteAccessTokenFromRefreshTokenSql = DEFAULT_ACCESS_TOKEN_DELETE_FROM_REFRESH_TOKEN_STATEMENT; - - private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator(); - - private final JdbcTemplate jdbcTemplate; - - public JdbcTokenStore(DataSource dataSource) { - Assert.notNull(dataSource, "DataSource required"); - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - public JdbcTokenStore(JdbcTemplate jdbcTemplate) { - Assert.notNull(jdbcTemplate, "jdbcTemplate required"); - this.jdbcTemplate = jdbcTemplate; - } - - public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) { - this.authenticationKeyGenerator = authenticationKeyGenerator; - } - - public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { - OAuth2AccessToken accessToken = null; - - String key = authenticationKeyGenerator.extractKey(authentication); - try { - accessToken = jdbcTemplate.queryForObject(selectAccessTokenFromAuthenticationSql, - new RowMapper() { - public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { - return deserializeAccessToken(rs.getBytes(2)); - } - }, key); - } catch (EmptyResultDataAccessException e) { - if (LOG.isInfoEnabled()) { - LOG.debug("Failed to find access token for authentication " + authentication); - } - } catch (IllegalArgumentException e) { - LOG.error("Could not extract access token for authentication " + authentication, e); - } - - if (accessToken != null - && !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) { - removeAccessToken(accessToken.getValue()); - // Keep the store consistent (maybe the same user is represented by this - // authentication but the details have - // changed) - storeAccessToken(accessToken, authentication); - } - return accessToken; - } - - public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { - String refreshToken = null; - if (token.getRefreshToken() != null) { - refreshToken = token.getRefreshToken().getValue(); - } - - if (readAccessToken(token.getValue()) != null) { - removeAccessToken(token.getValue()); - } - - jdbcTemplate.update(insertAccessTokenSql, - new Object[] { extractTokenKey(token.getValue()), new SqlLobValue(serializeAccessToken(token)), - authenticationKeyGenerator.extractKey(authentication), - authentication.isClientOnly() ? null : authentication.getName(), - authentication.getOAuth2Request().getClientId(), - new SqlLobValue(serializeAuthentication(authentication)), extractTokenKey(refreshToken) }, - new int[] { Types.VARCHAR, Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BLOB, - Types.VARCHAR }); - } - - public OAuth2AccessToken readAccessToken(String tokenValue) { - OAuth2AccessToken accessToken = null; - - try { - accessToken = jdbcTemplate.queryForObject(selectAccessTokenSql, new RowMapper() { - public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { - return deserializeAccessToken(rs.getBytes(2)); - } - }, extractTokenKey(tokenValue)); - } catch (EmptyResultDataAccessException e) { - if (LOG.isInfoEnabled()) { - LOG.info("Failed to find access token for token " + tokenValue); - } - } catch (IllegalArgumentException e) { - LOG.warn("Failed to deserialize access token for " + tokenValue, e); - removeAccessToken(tokenValue); - } - - return accessToken; - } - - public void removeAccessToken(OAuth2AccessToken token) { - removeAccessToken(token.getValue()); - } - - public void removeAccessToken(String tokenValue) { - jdbcTemplate.update(deleteAccessTokenSql, extractTokenKey(tokenValue)); - } - - public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { - return readAuthentication(token.getValue()); - } - - public OAuth2Authentication readAuthentication(String token) { - OAuth2Authentication authentication = null; - - try { - authentication = jdbcTemplate.queryForObject(selectAccessTokenAuthenticationSql, - new RowMapper() { - public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException { - return deserializeAuthentication(rs.getBytes(2)); - } - }, extractTokenKey(token)); - } catch (EmptyResultDataAccessException e) { - if (LOG.isInfoEnabled()) { - LOG.info("Failed to find access token for token " + token); - } - } catch (IllegalArgumentException e) { - LOG.warn("Failed to deserialize authentication for " + token, e); - removeAccessToken(token); - } - - return authentication; - } - - public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { - jdbcTemplate.update(insertRefreshTokenSql, - new Object[] { extractTokenKey(refreshToken.getValue()), - new SqlLobValue(serializeRefreshToken(refreshToken)), - new SqlLobValue(serializeAuthentication(authentication)) }, - new int[] { Types.VARCHAR, Types.BLOB, Types.BLOB }); - } - - public OAuth2RefreshToken readRefreshToken(String token) { - OAuth2RefreshToken refreshToken = null; - - try { - refreshToken = jdbcTemplate.queryForObject(selectRefreshTokenSql, new RowMapper() { - public OAuth2RefreshToken mapRow(ResultSet rs, int rowNum) throws SQLException { - return deserializeRefreshToken(rs.getBytes(2)); - } - }, extractTokenKey(token)); - } catch (EmptyResultDataAccessException e) { - if (LOG.isInfoEnabled()) { - LOG.info("Failed to find refresh token for token " + token); - } - } catch (IllegalArgumentException e) { - LOG.warn("Failed to deserialize refresh token for token " + token, e); - removeRefreshToken(token); - } - - return refreshToken; - } - - public void removeRefreshToken(OAuth2RefreshToken token) { - removeRefreshToken(token.getValue()); - } - - public void removeRefreshToken(String token) { - jdbcTemplate.update(deleteRefreshTokenSql, extractTokenKey(token)); - } - - public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { - return readAuthenticationForRefreshToken(token.getValue()); - } - - public OAuth2Authentication readAuthenticationForRefreshToken(String value) { - OAuth2Authentication authentication = null; - - try { - authentication = jdbcTemplate.queryForObject(selectRefreshTokenAuthenticationSql, - new RowMapper() { - public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException { - return deserializeAuthentication(rs.getBytes(2)); - } - }, extractTokenKey(value)); - } catch (EmptyResultDataAccessException e) { - if (LOG.isInfoEnabled()) { - LOG.info("Failed to find access token for token " + value); - } - } catch (IllegalArgumentException e) { - LOG.warn("Failed to deserialize access token for " + value, e); - removeRefreshToken(value); - } - - return authentication; - } - - public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { - removeAccessTokenUsingRefreshToken(refreshToken.getValue()); - } - - public void removeAccessTokenUsingRefreshToken(String refreshToken) { - jdbcTemplate.update(deleteAccessTokenFromRefreshTokenSql, new Object[] { extractTokenKey(refreshToken) }, - new int[] { Types.VARCHAR }); - } - - public Collection findTokensByClientId(String clientId) { - List accessTokens = new ArrayList(); - - try { - accessTokens = jdbcTemplate.query(selectAccessTokensFromClientIdSql, new SafeAccessTokenRowMapper(), - clientId); - } catch (EmptyResultDataAccessException e) { - if (LOG.isInfoEnabled()) { - LOG.info("Failed to find access token for clientId " + clientId); - } - } - accessTokens = removeNulls(accessTokens); - - return accessTokens; - } - - public Collection findTokensByUserName(String userName) { - List accessTokens = new ArrayList(); - - try { - accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameSql, new SafeAccessTokenRowMapper(), - userName); - } catch (EmptyResultDataAccessException e) { - if (LOG.isInfoEnabled()) - LOG.info("Failed to find access token for userName " + userName); - } - accessTokens = removeNulls(accessTokens); - - return accessTokens; - } - - public Collection findTokensByClientIdAndUserName(String clientId, String userName) { - List accessTokens = new ArrayList(); - - try { - accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameAndClientIdSql, - new SafeAccessTokenRowMapper(), userName, clientId); - } catch (EmptyResultDataAccessException e) { - if (LOG.isInfoEnabled()) { - LOG.info("Failed to find access token for clientId " + clientId + " and userName " + userName); - } - } - accessTokens = removeNulls(accessTokens); - - return accessTokens; - } - - private List removeNulls(List accessTokens) { - List tokens = new ArrayList(); - for (OAuth2AccessToken token : accessTokens) { - if (token != null) { - tokens.add(token); - } - } - return tokens; - } - - protected String extractTokenKey(String value) { - if (value == null) { - return null; - } - MessageDigest digest; - try { - digest = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK)."); - } - - try { - byte[] bytes = digest.digest(value.getBytes("UTF-8")); - return String.format("%032x", new BigInteger(1, bytes)); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); - } - } - - private final class SafeAccessTokenRowMapper implements RowMapper { - public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { - try { - return deserializeAccessToken(rs.getBytes(2)); - } catch (IllegalArgumentException e) { - String token = rs.getString(1); - jdbcTemplate.update(deleteAccessTokenSql, token); - return null; - } - } - } - - protected byte[] serializeAccessToken(OAuth2AccessToken token) { - return SerializationUtils.serialize(token); - } - - protected byte[] serializeRefreshToken(OAuth2RefreshToken token) { - return SerializationUtils.serialize(token); - } - - protected byte[] serializeAuthentication(OAuth2Authentication authentication) { - return SerializationUtils.serialize(authentication); - } - - protected OAuth2AccessToken deserializeAccessToken(byte[] token) { - return SerializationUtils.deserialize(token); - } - - protected OAuth2RefreshToken deserializeRefreshToken(byte[] token) { - return SerializationUtils.deserialize(token); - } - - protected OAuth2Authentication deserializeAuthentication(byte[] authentication) { - return SerializationUtils.deserialize(authentication); - } - - public void setInsertAccessTokenSql(String insertAccessTokenSql) { - this.insertAccessTokenSql = insertAccessTokenSql; - } - - public void setSelectAccessTokenSql(String selectAccessTokenSql) { - this.selectAccessTokenSql = selectAccessTokenSql; - } - - public void setDeleteAccessTokenSql(String deleteAccessTokenSql) { - this.deleteAccessTokenSql = deleteAccessTokenSql; - } - - public void setInsertRefreshTokenSql(String insertRefreshTokenSql) { - this.insertRefreshTokenSql = insertRefreshTokenSql; - } - - public void setSelectRefreshTokenSql(String selectRefreshTokenSql) { - this.selectRefreshTokenSql = selectRefreshTokenSql; - } - - public void setDeleteRefreshTokenSql(String deleteRefreshTokenSql) { - this.deleteRefreshTokenSql = deleteRefreshTokenSql; - } - - public void setSelectAccessTokenAuthenticationSql(String selectAccessTokenAuthenticationSql) { - this.selectAccessTokenAuthenticationSql = selectAccessTokenAuthenticationSql; - } - - public void setSelectRefreshTokenAuthenticationSql(String selectRefreshTokenAuthenticationSql) { - this.selectRefreshTokenAuthenticationSql = selectRefreshTokenAuthenticationSql; - } - - public void setSelectAccessTokenFromAuthenticationSql(String selectAccessTokenFromAuthenticationSql) { - this.selectAccessTokenFromAuthenticationSql = selectAccessTokenFromAuthenticationSql; - } - - public void setDeleteAccessTokenFromRefreshTokenSql(String deleteAccessTokenFromRefreshTokenSql) { - this.deleteAccessTokenFromRefreshTokenSql = deleteAccessTokenFromRefreshTokenSql; - } - - public void setSelectAccessTokensFromUserNameSql(String selectAccessTokensFromUserNameSql) { - this.selectAccessTokensFromUserNameSql = selectAccessTokensFromUserNameSql; - } - - public void setSelectAccessTokensFromUserNameAndClientIdSql(String selectAccessTokensFromUserNameAndClientIdSql) { - this.selectAccessTokensFromUserNameAndClientIdSql = selectAccessTokensFromUserNameAndClientIdSql; - } - - public void setSelectAccessTokensFromClientIdSql(String selectAccessTokensFromClientIdSql) { - this.selectAccessTokensFromClientIdSql = selectAccessTokensFromClientIdSql; - } -} diff --git a/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtConfig.java b/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtConfig.java index e82dac9ac..df114a74f 100644 --- a/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtConfig.java +++ b/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtConfig.java @@ -22,7 +22,6 @@ import org.maxkey.authz.oauth2.provider.client.JdbcClientDetailsService; import org.maxkey.authz.oauth2.provider.token.DefaultTokenServices; import org.maxkey.authz.oauth2.provider.token.TokenStore; import org.maxkey.authz.oauth2.provider.token.store.InMemoryTokenStore; -import org.maxkey.authz.oauth2.provider.token.store.JdbcTokenStore; import org.maxkey.authz.oauth2.provider.token.store.RedisTokenStore; import org.maxkey.jobs.DynamicGroupsJob; import org.maxkey.password.onetimepwd.AbstractOtpAuthn; @@ -79,16 +78,14 @@ public class MaxKeyMgtConfig implements InitializingBean { JdbcTemplate jdbcTemplate, RedisConnectionFactory jedisConnectionFactory) { TokenStore tokenStore = null; - if (persistence == 0) { - tokenStore = new InMemoryTokenStore(); - _logger.debug("InMemoryTokenStore"); - } else if (persistence == 1) { - tokenStore = new JdbcTokenStore(jdbcTemplate); - _logger.debug("JdbcTokenStore"); - } else if (persistence == 2) { + if (persistence == 2) { tokenStore = new RedisTokenStore(jedisConnectionFactory); _logger.debug("RedisTokenStore"); + }else { + tokenStore = new InMemoryTokenStore(); + _logger.debug("InMemoryTokenStore"); } + return tokenStore; } diff --git a/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/interceptor/RestApiPermissionAdapter.java b/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/interceptor/RestApiPermissionAdapter.java index 834a17295..8c7baaf8d 100644 --- a/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/interceptor/RestApiPermissionAdapter.java +++ b/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/interceptor/RestApiPermissionAdapter.java @@ -17,16 +17,12 @@ package org.maxkey.web.interceptor; -import java.time.Duration; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.ehcache.UserManagedCache; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.UserManagedCacheBuilder; -import org.maxkey.constants.ConstantsTimeInterval; import org.maxkey.crypto.password.PasswordReciprocal; import org.maxkey.entity.apps.Apps; import org.maxkey.persistence.service.AppsService; @@ -39,6 +35,9 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.springframework.web.servlet.AsyncHandlerInterceptor; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + /** * basic认证Interceptor处理. * @author Crystal.Sea @@ -48,14 +47,10 @@ import org.springframework.web.servlet.AsyncHandlerInterceptor; public class RestApiPermissionAdapter implements AsyncHandlerInterceptor { private static final Logger _logger = LoggerFactory.getLogger(RestApiPermissionAdapter.class); - protected static final UserManagedCache appsCacheStore = - UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, Apps.class) - .withExpiry( - ExpiryPolicyBuilder.timeToLiveExpiration( - Duration.ofMinutes(ConstantsTimeInterval.ONE_HOUR) - ) - ) - .build(true); + protected static final Cache appsCacheStore = + Caffeine.newBuilder() + .expireAfterWrite(60, TimeUnit.MINUTES) + .build(); @Autowired AppsService appsService; @@ -83,7 +78,7 @@ public class RestApiPermissionAdapter implements AsyncHandlerInterceptor { String appId = headerCredential.getUsername(); String appSecret = headerCredential.getCredential(); _logger.trace("appId "+ appId+" , appSecret " + appSecret); - Apps app = appsCacheStore.get(appId); + Apps app = appsCacheStore.getIfPresent(appId); if (app == null) { app = appsService.get(appId); appsCacheStore.put(appId, app);