diff --git a/kernel-d-auth/auth-sdk/pom.xml b/kernel-d-auth/auth-sdk/pom.xml index 8d00a7a83..76519ce78 100644 --- a/kernel-d-auth/auth-sdk/pom.xml +++ b/kernel-d-auth/auth-sdk/pom.xml @@ -59,12 +59,24 @@ spring-web - + - org.springframework.boot - spring-boot-starter-data-redis - true + com.sedinbj.kernel + cache-api + 1.0.0 + + + com.sedinbj.kernel + cache-sdk-memory + 1.0.0 + provided + + + com.sedinbj.kernel + cache-sdk-redis + 1.0.0 + provided diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/MemoryCacheSessionManager.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/DefaultSessionManager.java similarity index 51% rename from kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/MemoryCacheSessionManager.java rename to kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/DefaultSessionManager.java index 1455de941..d2033b044 100644 --- a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/MemoryCacheSessionManager.java +++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/DefaultSessionManager.java @@ -1,32 +1,26 @@ package cn.stylefeng.roses.kernel.auth.session; - -import cn.hutool.cache.impl.TimedCache; import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi; import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; +import com.sedinbj.kernel.cache.api.CacheOperatorApi; -import java.util.HashMap; import java.util.HashSet; -import java.util.Map; import java.util.Set; -import static cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants.LOGGED_TOKEN_PREFIX; -import static cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants.LOGGED_USERID_PREFIX; - /** - * 基于内存的会话管理 + * 基于redis的会话管理 * * @author fengshuonan * @date 2019-09-28-14:43 */ -public class MemoryCacheSessionManager implements SessionManagerApi { +public class DefaultSessionManager implements SessionManagerApi { /** * 登录用户缓存 *

* key是 LOGGED_TOKEN_PREFIX + 用户的token */ - private final TimedCache loginUserCache; + private final CacheOperatorApi loginUserCache; /** * 用户token的缓存,这个缓存用来存储一个用户的所有token @@ -37,57 +31,60 @@ public class MemoryCacheSessionManager implements SessionManagerApi { *

* 这个缓存应该定时刷新下,因为有过期token的用户,所以这个里边的值set得清理 */ - private final Map> loginTokenCache = new HashMap<>(); + private final CacheOperatorApi> allPlaceLoginTokenCache; - public MemoryCacheSessionManager(TimedCache loginUserCache) { + /** + * session的超时时间 + */ + private final Long sessionExpiredSeconds; + + public DefaultSessionManager(CacheOperatorApi loginUserCache, CacheOperatorApi> allPlaceLoginTokenCache, Long sessionExpiredSeconds) { this.loginUserCache = loginUserCache; + this.allPlaceLoginTokenCache = allPlaceLoginTokenCache; + this.sessionExpiredSeconds = sessionExpiredSeconds; } @Override public void createSession(String token, LoginUser loginUser) { // 装配用户信息的缓存 - loginUserCache.put(getTokenKey(token), loginUser); + loginUserCache.put(token, loginUser, sessionExpiredSeconds); // 装配用户token的缓存 - String userIdKey = getUserIdKey(loginUser.getUserId()); - Set theUserTokens = loginTokenCache.get(userIdKey); + Set theUserTokens = allPlaceLoginTokenCache.get(loginUser.getUserId().toString()); if (theUserTokens == null) { - HashSet tempUserTokens = new HashSet<>(); - tempUserTokens.add(token); - loginTokenCache.put(userIdKey, tempUserTokens); - } else { - theUserTokens.add(token); + theUserTokens = new HashSet<>(); } + theUserTokens.add(token); + allPlaceLoginTokenCache.put(loginUser.getUserId().toString(), theUserTokens); } @Override public LoginUser getSession(String token) { - return loginUserCache.get(getTokenKey(token)); + return loginUserCache.get(token); } @Override public void removeSession(String token) { - String tokenKey = getTokenKey(token); - LoginUser loginUser = loginUserCache.get(tokenKey); + LoginUser loginUser = loginUserCache.get(token); - // 删除用户id对应token的缓存 + // 删除本token用户信息的缓存 + loginUserCache.remove(token); + + // 删除多端登录信息 if (loginUser != null) { Long userId = loginUser.getUserId(); - Set userTokens = loginTokenCache.get(getUserIdKey(userId)); + Set userTokens = allPlaceLoginTokenCache.get(userId.toString()); if (userTokens != null) { userTokens.remove(token); // 如果删除后size为0,则把整个key删掉 if (userTokens.size() == 0) { - loginTokenCache.remove(getUserIdKey(userId)); + allPlaceLoginTokenCache.remove(userId.toString()); } } } - - // 删除用户信息的缓存 - loginUserCache.remove(getTokenKey(token)); } @Override @@ -107,40 +104,20 @@ public class MemoryCacheSessionManager implements SessionManagerApi { // 设置用户id对应的token列表为参数token HashSet tokenSet = new HashSet<>(); tokenSet.add(token); - loginTokenCache.put(getUserIdKey(userId), tokenSet); + allPlaceLoginTokenCache.put(userId.toString(), tokenSet); } @Override public boolean haveSession(String token) { - return loginUserCache.containsKey(getTokenKey(token)); + return loginUserCache.contains(token); } @Override public void refreshSession(String token) { - LoginUser loginUser = loginUserCache.get(getTokenKey(token)); + LoginUser loginUser = loginUserCache.get(token); if (loginUser != null) { - loginUserCache.put(LOGGED_TOKEN_PREFIX + token, loginUser, loginUserCache.timeout()); + loginUserCache.expire(token, sessionExpiredSeconds); } } - /** - * 获取token的缓存key - * - * @author fengshuonan - * @date 2020/10/21 15:09 - */ - private String getTokenKey(String token) { - return LOGGED_TOKEN_PREFIX + token; - } - - /** - * 获取用户id的缓存key - * - * @author fengshuonan - * @date 2020/10/21 15:10 - */ - private String getUserIdKey(Long userId) { - return LOGGED_USERID_PREFIX + userId; - } - } diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/RedisSessionManager.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/RedisSessionManager.java deleted file mode 100644 index dc5199eb0..000000000 --- a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/RedisSessionManager.java +++ /dev/null @@ -1,159 +0,0 @@ -package cn.stylefeng.roses.kernel.auth.session; - -import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi; -import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; -import com.alibaba.fastjson.parser.ParserConfig; -import org.springframework.data.redis.core.RedisTemplate; - -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import static cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants.LOGGED_TOKEN_PREFIX; -import static cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants.LOGGED_USERID_PREFIX; - -/** - * 基于redis的会话管理 - * - * @author fengshuonan - * @date 2019-09-28-14:43 - */ -public class RedisSessionManager implements SessionManagerApi { - - /** - * 登录用户缓存 - *

- * key是 LOGGED_TOKEN_PREFIX + 用户的token - */ - private final RedisTemplate loginUserRedisTemplate; - - /** - * 用户token的缓存,这个缓存用来存储一个用户的所有token - *

- * 没开启单端限制的话,一个用户可能有多个token,因为一个用户可能在多个地点或打开多个浏览器访问系统 - *

- * key是 LOGGED_USERID_PREFIX + 用户id - *

- * 这个缓存应该定时刷新下,因为有过期token的用户,所以这个里边的值set得清理 - */ - private final RedisTemplate> loginTokenRedisTemplate; - - /** - * session的超时时间 - */ - private final Long sessionExpiredSeconds; - - public RedisSessionManager(RedisTemplate loginUserRedisTemplate, RedisTemplate> loginTokenRedisTemplate, Long sessionExpiredSeconds) { - this.loginUserRedisTemplate = loginUserRedisTemplate; - this.loginTokenRedisTemplate = loginTokenRedisTemplate; - this.sessionExpiredSeconds = sessionExpiredSeconds; - } - - @Override - public void createSession(String token, LoginUser loginUser) { - ParserConfig.getGlobalInstance().setAutoTypeSupport(true); - - // 装配用户信息的缓存 - loginUserRedisTemplate.opsForValue().set(getTokenKey(token), loginUser, sessionExpiredSeconds, TimeUnit.SECONDS); - - // 装配用户token的缓存 - String userIdKey = getUserIdKey(loginUser.getUserId()); - Set theUserTokens = loginTokenRedisTemplate.opsForValue().get(userIdKey); - if (theUserTokens == null) { - HashSet tempUserTokens = new HashSet<>(); - tempUserTokens.add(token); - loginTokenRedisTemplate.opsForValue().set(userIdKey, tempUserTokens); - } else { - theUserTokens.add(token); - } - } - - @Override - public LoginUser getSession(String token) { - ParserConfig.getGlobalInstance().setAutoTypeSupport(true); - return loginUserRedisTemplate.opsForValue().get(getTokenKey(token)); - } - - @Override - public void removeSession(String token) { - - String tokenKey = getTokenKey(token); - LoginUser loginUser = loginUserRedisTemplate.opsForValue().get(tokenKey); - - // 删除用户id对应token的缓存 - if (loginUser != null) { - Long userId = loginUser.getUserId(); - Set userTokens = loginTokenRedisTemplate.opsForValue().get(getUserIdKey(userId)); - if (userTokens != null) { - userTokens.remove(token); - - // 如果删除后size为0,则把整个key删掉 - if (userTokens.size() == 0) { - loginUserRedisTemplate.delete(getUserIdKey(userId)); - } - } - } - - // 删除用户信息的缓存 - loginUserRedisTemplate.delete(getTokenKey(token)); - } - - @Override - public void removeSessionExcludeToken(String token) { - - // 获取token对应的会话 - LoginUser session = this.getSession(token); - - // 如果会话为空,直接返回 - if (session == null) { - return; - } - - // 获取用户id - Long userId = session.getUserId(); - - // 设置用户id对应的token列表为参数token - HashSet tokenSet = new HashSet<>(); - tokenSet.add(token); - loginTokenRedisTemplate.opsForValue().set(getUserIdKey(userId), tokenSet); - } - - @Override - public boolean haveSession(String token) { - Boolean flag = loginUserRedisTemplate.hasKey(getTokenKey(token)); - if (flag == null) { - return false; - } else { - return flag; - } - } - - @Override - public void refreshSession(String token) { - LoginUser loginUser = loginUserRedisTemplate.boundValueOps(getTokenKey(token)).get(); - if (loginUser != null) { - loginUserRedisTemplate.boundValueOps(getTokenKey(token)).expire(sessionExpiredSeconds, TimeUnit.SECONDS); - } - } - - /** - * 获取token的缓存key - * - * @author fengshuonan - * @date 2020/10/21 15:09 - */ - private String getTokenKey(String token) { - return LOGGED_TOKEN_PREFIX + token; - } - - /** - * 获取用户id的缓存key - * - * @author fengshuonan - * @date 2020/10/21 15:10 - */ - private String getUserIdKey(Long userId) { - return LOGGED_USERID_PREFIX + userId; - } - -} diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/logintoken/MemoryLoginTokenCache.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/logintoken/MemoryLoginTokenCache.java new file mode 100644 index 000000000..1badc23ea --- /dev/null +++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/logintoken/MemoryLoginTokenCache.java @@ -0,0 +1,28 @@ +package cn.stylefeng.roses.kernel.auth.session.cache.logintoken; + +import cn.hutool.cache.impl.TimedCache; +import com.sedinbj.kernel.cache.AbstractMemoryCacheOperator; + +import java.util.Set; + +import static cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants.LOGGED_USERID_PREFIX; + + +/** + * 基于内存的token缓存 + * + * @author fengshuonan + * @date 2020/12/24 19:16 + */ +public class MemoryLoginTokenCache extends AbstractMemoryCacheOperator> { + + public MemoryLoginTokenCache(TimedCache> timedCache) { + super(timedCache); + } + + @Override + public String getCommonKeyPrefix() { + return LOGGED_USERID_PREFIX; + } + +} diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/logintoken/RedisLoginTokenCache.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/logintoken/RedisLoginTokenCache.java new file mode 100644 index 000000000..b19da3dbb --- /dev/null +++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/logintoken/RedisLoginTokenCache.java @@ -0,0 +1,28 @@ +package cn.stylefeng.roses.kernel.auth.session.cache.logintoken; + +import com.sedinbj.kernel.cache.AbstractRedisCacheOperator; +import org.springframework.data.redis.core.RedisTemplate; + +import java.util.Set; + +import static cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants.LOGGED_USERID_PREFIX; + + +/** + * 基于redis的token的缓存 + * + * @author fengshuonan + * @date 2020/12/24 19:16 + */ +public class RedisLoginTokenCache extends AbstractRedisCacheOperator> { + + public RedisLoginTokenCache(RedisTemplate> redisTemplate) { + super(redisTemplate); + } + + @Override + public String getCommonKeyPrefix() { + return LOGGED_USERID_PREFIX; + } + +} diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/loginuser/MemoryLoginUserCache.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/loginuser/MemoryLoginUserCache.java new file mode 100644 index 000000000..330b6b1cc --- /dev/null +++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/loginuser/MemoryLoginUserCache.java @@ -0,0 +1,26 @@ +package cn.stylefeng.roses.kernel.auth.session.cache.loginuser; + +import cn.hutool.cache.impl.TimedCache; +import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; +import com.sedinbj.kernel.cache.AbstractMemoryCacheOperator; + +import static cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants.LOGGED_TOKEN_PREFIX; + +/** + * 基于内存的登录用户缓存 + * + * @author fengshuonan + * @date 2020/12/24 19:16 + */ +public class MemoryLoginUserCache extends AbstractMemoryCacheOperator { + + public MemoryLoginUserCache(TimedCache timedCache) { + super(timedCache); + } + + @Override + public String getCommonKeyPrefix() { + return LOGGED_TOKEN_PREFIX; + } + +} diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/loginuser/RedisLoginUserCache.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/loginuser/RedisLoginUserCache.java new file mode 100644 index 000000000..cb0fcf3f8 --- /dev/null +++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cache/loginuser/RedisLoginUserCache.java @@ -0,0 +1,27 @@ +package cn.stylefeng.roses.kernel.auth.session.cache.loginuser; + +import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; +import com.sedinbj.kernel.cache.AbstractRedisCacheOperator; +import org.springframework.data.redis.core.RedisTemplate; + +import static cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants.LOGGED_TOKEN_PREFIX; + + +/** + * 基于redis的登录用户缓存 + * + * @author fengshuonan + * @date 2020/12/24 19:16 + */ +public class RedisLoginUserCache extends AbstractRedisCacheOperator { + + public RedisLoginUserCache(RedisTemplate redisTemplate) { + super(redisTemplate); + } + + @Override + public String getCommonKeyPrefix() { + return LOGGED_TOKEN_PREFIX; + } + +} diff --git a/kernel-d-auth/auth-spring-boot-starter/pom.xml b/kernel-d-auth/auth-spring-boot-starter/pom.xml index 28685f1f1..f032f0fde 100644 --- a/kernel-d-auth/auth-spring-boot-starter/pom.xml +++ b/kernel-d-auth/auth-spring-boot-starter/pom.xml @@ -24,6 +24,13 @@ 1.0.0 + + + com.sedinbj.kernel + cache-sdk-memory + 1.0.0 + + diff --git a/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/GunsAuthAutoConfiguration.java b/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/GunsAuthAutoConfiguration.java index 666706c7e..a1ea8884b 100644 --- a/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/GunsAuthAutoConfiguration.java +++ b/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/GunsAuthAutoConfiguration.java @@ -1,17 +1,25 @@ package cn.stylefeng.roses.kernel.auth.starter; import cn.hutool.cache.CacheUtil; +import cn.hutool.cache.impl.TimedCache; import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi; import cn.stylefeng.roses.kernel.auth.api.expander.AuthConfigExpander; import cn.stylefeng.roses.kernel.auth.api.password.PasswordStoredEncryptApi; import cn.stylefeng.roses.kernel.auth.api.password.PasswordTransferEncryptApi; +import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; import cn.stylefeng.roses.kernel.auth.password.BcryptPasswordStoredEncrypt; import cn.stylefeng.roses.kernel.auth.password.RsaPasswordTransferEncrypt; -import cn.stylefeng.roses.kernel.auth.session.MemoryCacheSessionManager; +import cn.stylefeng.roses.kernel.auth.session.DefaultSessionManager; +import cn.stylefeng.roses.kernel.auth.session.cache.logintoken.MemoryLoginTokenCache; +import cn.stylefeng.roses.kernel.auth.session.cache.loginuser.MemoryLoginUserCache; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import java.util.Set; + +import static com.sedinbj.kernel.cache.api.constants.CacheConstants.NONE_EXPIRED_TIME; + /** * 认证和鉴权模块的自动配置 * @@ -57,7 +65,14 @@ public class GunsAuthAutoConfiguration { @ConditionalOnMissingBean(SessionManagerApi.class) public SessionManagerApi sessionManagerApi() { Long sessionExpiredSeconds = AuthConfigExpander.getSessionExpiredSeconds(); - return new MemoryCacheSessionManager(CacheUtil.newTimedCache(sessionExpiredSeconds * 1000)); + + TimedCache loginUsers = CacheUtil.newTimedCache(1000L * sessionExpiredSeconds); + TimedCache> loginTokens = CacheUtil.newTimedCache(NONE_EXPIRED_TIME); + + MemoryLoginUserCache memoryLoginUserCache = new MemoryLoginUserCache(loginUsers); + MemoryLoginTokenCache memoryLoginTokenCache = new MemoryLoginTokenCache(loginTokens); + + return new DefaultSessionManager(memoryLoginUserCache, memoryLoginTokenCache, sessionExpiredSeconds); } }