mirror of
https://gitee.com/dromara/MaxKey.git
synced 2025-12-07 01:18:27 +08:00
cache change to Caffeine
This commit is contained in:
parent
8b3c035102
commit
f7966f5b12
@ -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}"
|
||||
|
||||
@ -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}"
|
||||
|
||||
@ -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}"
|
||||
|
||||
@ -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}"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<String, OnlineTicket> onlineTicketStore =
|
||||
UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, OnlineTicket.class)
|
||||
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(30)))
|
||||
.build(true);
|
||||
|
||||
protected static Cache<String, OnlineTicket> 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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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<String, RemeberMe> remeberMeStore =
|
||||
UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, RemeberMe.class)
|
||||
.withExpiry(
|
||||
ExpiryPolicyBuilder.timeToLiveExpiration(
|
||||
Duration.ofMinutes(ConstantsTimeInterval.TWO_WEEK)
|
||||
)
|
||||
)
|
||||
.build(true);
|
||||
protected static final Cache<String, RemeberMe> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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<String, OneTimePassword> optTokenStore =
|
||||
UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, OneTimePassword.class)
|
||||
.withExpiry(
|
||||
ExpiryPolicyBuilder.timeToLiveExpiration(
|
||||
java.time.Duration.ofMinutes(ConstantsTimeInterval.ONE_MINUTE * 5)
|
||||
)
|
||||
)
|
||||
.build(true);
|
||||
protected static final Cache<String, OneTimePassword> 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(),
|
||||
|
||||
@ -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<String, PasswordPolicy> passwordPolicyStore =
|
||||
UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, PasswordPolicy.class)
|
||||
.withExpiry(
|
||||
ExpiryPolicyBuilder.timeToLiveExpiration(
|
||||
java.time.Duration.ofMinutes(ConstantsTimeInterval.ONE_HOUR)
|
||||
)
|
||||
)
|
||||
.build(true);
|
||||
protected static final Cache<String, PasswordPolicy> 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,
|
||||
|
||||
Binary file not shown.
BIN
maxkey-lib/mybatis-jpa-extra-2.6.jar
Normal file
BIN
maxkey-lib/mybatis-jpa-extra-2.6.jar
Normal file
Binary file not shown.
Binary file not shown.
@ -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<Apps>{
|
||||
|
||||
protected final static UserManagedCache<String, Apps> appsDetailsCacheStore =
|
||||
UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, Apps.class)
|
||||
.withExpiry(
|
||||
ExpiryPolicyBuilder.timeToLiveExpiration(
|
||||
Duration.ofHours(1)
|
||||
)
|
||||
)
|
||||
.build(true);
|
||||
protected final static Cache<String, Apps> appsDetailsCacheStore =
|
||||
Caffeine.newBuilder()
|
||||
.expireAfterWrite(60, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
public AppsService() {
|
||||
super(AppsMapper.class);
|
||||
@ -50,7 +46,6 @@ public class AppsService extends JpaBaseService<Apps>{
|
||||
*/
|
||||
@Override
|
||||
public AppsMapper getMapper() {
|
||||
// TODO Auto-generated method stub
|
||||
return (AppsMapper)super.getMapper();
|
||||
}
|
||||
|
||||
@ -75,7 +70,7 @@ public class AppsService extends JpaBaseService<Apps>{
|
||||
}
|
||||
|
||||
public Apps getCacheAppDetails(String appId) {
|
||||
Apps appDetails=appsDetailsCacheStore.get(appId);
|
||||
Apps appDetails=appsDetailsCacheStore.getIfPresent(appId);
|
||||
return appDetails;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<String, Ticket> casTicketStore =
|
||||
UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, Ticket.class)
|
||||
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofHours(1)))
|
||||
.build(true);
|
||||
protected final static Cache<String, Ticket> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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<String, Ticket> casTicketStore =
|
||||
UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, Ticket.class)
|
||||
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(60)))
|
||||
.build(true);
|
||||
protected final static Cache<String, Ticket> 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;
|
||||
}
|
||||
|
||||
|
||||
@ -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<String, Ticket> casTicketGrantingTicketStore =
|
||||
UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, Ticket.class)
|
||||
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofDays(2)))
|
||||
.build(true);
|
||||
|
||||
protected final static Cache<String, Ticket> 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;
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
*
|
||||
|
||||
@ -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";
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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<String, String> scopes = new LinkedHashMap<String, String>();
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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<String, String> scopes = new LinkedHashMap<String, String>();
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<String, ClientDetails> clientDetailsStore = new HashMap<String, ClientDetails>();
|
||||
|
||||
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<String, ? extends ClientDetails> clientDetailsStore) {
|
||||
this.clientDetailsStore = new HashMap<String, ClientDetails>(clientDetailsStore);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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<String, ClientDetails> 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;
|
||||
}
|
||||
|
||||
|
||||
@ -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<String, OAuth2Authentication> authorizationCodeStore =
|
||||
UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, OAuth2Authentication.class)
|
||||
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(60)))
|
||||
.build(true);
|
||||
protected final static Cache<String, OAuth2Authentication> 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;
|
||||
}
|
||||
|
||||
|
||||
@ -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<OAuth2Authentication>() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -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<String, String> approvalParameters,
|
||||
Map<String, ?> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ public class TokenEndpointAuthenticationFilter implements Filter {
|
||||
}
|
||||
|
||||
Map<String, String> 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));
|
||||
|
||||
@ -69,14 +69,14 @@ public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory {
|
||||
|
||||
public AuthorizationRequest createAuthorizationRequest(Map<String, String> 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<String> responseTypes = OAuth2Utils.parseParameterList(authorizationParameters
|
||||
.get(OAuth2Utils.RESPONSE_TYPE));
|
||||
.get(OAuth2Constants.PARAMETER.RESPONSE_TYPE));
|
||||
|
||||
Set<String> scopes = extractScopes(authorizationParameters, clientId);
|
||||
|
||||
@ -97,7 +97,7 @@ public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory {
|
||||
|
||||
public TokenRequest createTokenRequest(Map<String, String> 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<String> scopes = extractScopes(requestParameters, clientId);
|
||||
TokenRequest tokenRequest = new TokenRequest(requestParameters, clientId, scopes, grantType);
|
||||
@ -127,7 +127,7 @@ public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory {
|
||||
}
|
||||
|
||||
private Set<String> extractScopes(Map<String, String> requestParameters, String clientId) {
|
||||
Set<String> scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Utils.SCOPE));
|
||||
Set<String> scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Constants.PARAMETER.SCOPE));
|
||||
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
|
||||
|
||||
if ((scopes == null || scopes.isEmpty())) {
|
||||
|
||||
@ -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<OAuth2AccessToken>() {
|
||||
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<OAuth2AccessToken>() {
|
||||
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<OAuth2Authentication>() {
|
||||
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<OAuth2RefreshToken>() {
|
||||
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<OAuth2Authentication>() {
|
||||
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<OAuth2AccessToken> findTokensByClientId(String clientId) {
|
||||
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
|
||||
|
||||
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<OAuth2AccessToken> findTokensByUserName(String userName) {
|
||||
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
|
||||
|
||||
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<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) {
|
||||
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
|
||||
|
||||
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<OAuth2AccessToken> removeNulls(List<OAuth2AccessToken> accessTokens) {
|
||||
List<OAuth2AccessToken> tokens = new ArrayList<OAuth2AccessToken>();
|
||||
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<OAuth2AccessToken> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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<String, Apps> appsCacheStore =
|
||||
UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, Apps.class)
|
||||
.withExpiry(
|
||||
ExpiryPolicyBuilder.timeToLiveExpiration(
|
||||
Duration.ofMinutes(ConstantsTimeInterval.ONE_HOUR)
|
||||
)
|
||||
)
|
||||
.build(true);
|
||||
protected static final Cache<String, Apps> 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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user