|
@@ -0,0 +1,237 @@
|
|
|
|
+package com.dragoninfo.dcuc.auth.business.impl;
|
|
|
|
+
|
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
|
+import com.dragoninfo.dcuc.auth.auth.dto.AppAuthResultDto;
|
|
|
|
+import com.dragoninfo.dcuc.auth.business.ICacheBusiness;
|
|
|
|
+import com.dragoninfo.dcuc.auth.constance.AuthRedisConstant;
|
|
|
|
+import com.dragoninfo.dcuc.auth.token.enums.TokenActionEnum;
|
|
|
|
+import com.dragoninfo.dcuc.auth.token.enums.TokenTypeEnum;
|
|
|
|
+import com.dragoninfo.dcuc.auth.token.vo.AppTokenInfoRespVO;
|
|
|
|
+import com.dragoninfo.dcuc.auth.token.vo.UserTokenInfoRespVO;
|
|
|
|
+import com.dragonsoft.duceap.base.exception.ApplicationException;
|
|
|
|
+import com.dragonsoft.duceap.commons.util.collections.CollectionUtils;
|
|
|
|
+import com.dragonsoft.duceap.commons.util.string.StringUtils;
|
|
|
|
+import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+
|
|
|
|
+import javax.annotation.Resource;
|
|
|
|
+import java.util.*;
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @author mazq
|
|
|
|
+ * @date 2023/3/8
|
|
|
|
+ */
|
|
|
|
+@Service
|
|
|
|
+public class RedisCacheBusinessImpl implements ICacheBusiness {
|
|
|
|
+ /**
|
|
|
|
+ * 人员openId和userTokenId关联key类型
|
|
|
|
+ */
|
|
|
|
+ private static final String USER_OPEN_ID_TOKEN_ID_KEY_TYPE = "OPEN_TOKEN_ID";
|
|
|
|
+ /**
|
|
|
|
+ * 人员opId和appId关联key类型
|
|
|
|
+ */
|
|
|
|
+ private static final String USER_OPEN_ID_APP_ID_KEY_TYPE = "OPEN_APP_ID";
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ private StringRedisTemplate stringRedisTemplate;
|
|
|
|
+
|
|
|
|
+ private void cacheUserToken(UserTokenInfoRespVO userToken) {
|
|
|
|
+ // 缓存人员令牌
|
|
|
|
+ long tokenExpireTime = userToken.getExpireAt().getTime();
|
|
|
|
+ long redisExpire = (tokenExpireTime - System.currentTimeMillis()) / 1000;
|
|
|
|
+ String tokenIdKey = getKeyPrefix(userToken.getUserTokenId(), TokenTypeEnum.USER.getValue());
|
|
|
|
+ stringRedisTemplate.opsForValue().set(tokenIdKey, JSON.toJSONString(userToken), redisExpire, TimeUnit.SECONDS);
|
|
|
|
+
|
|
|
|
+ // 缓存openId-tokenId到缓存中
|
|
|
|
+ String pid = userToken.getPid();
|
|
|
|
+ String openIdTokenKey = getKeyPrefix(pid, USER_OPEN_ID_TOKEN_ID_KEY_TYPE);
|
|
|
|
+ stringRedisTemplate
|
|
|
|
+ .opsForValue()
|
|
|
|
+ .set(openIdTokenKey, userToken.getUserTokenId(), redisExpire, TimeUnit.SECONDS);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void cacheAppToken(AppTokenInfoRespVO appToken) {
|
|
|
|
+ long tokenExpireTime = appToken.getExpireAt().getTime();
|
|
|
|
+ long redisExpire = (tokenExpireTime - System.currentTimeMillis()) / 1000;
|
|
|
|
+ String key = getKeyPrefix(appToken.getAppTokenId(), TokenTypeEnum.APP.getValue());
|
|
|
|
+ stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(appToken), redisExpire, TimeUnit.SECONDS);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void renewUserToken(UserTokenInfoRespVO userTokenInfo) {
|
|
|
|
+ cacheUserToken(userTokenInfo);
|
|
|
|
+ // 如果存在其他相关信息刷新缓存
|
|
|
|
+ String pId = userTokenInfo.getPid();
|
|
|
|
+ String openIdAppIdKey = getKeyPrefix(pId, USER_OPEN_ID_APP_ID_KEY_TYPE);
|
|
|
|
+ long tokenExpireTime = userTokenInfo.getExpireAt().getTime();
|
|
|
|
+ long redisExpire = (tokenExpireTime - System.currentTimeMillis()) / 1000;
|
|
|
|
+ // 刷新应用鉴权结果, 不存在应用鉴权结果也没事
|
|
|
|
+ stringRedisTemplate.expire(openIdAppIdKey, redisExpire, TimeUnit.SECONDS);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void deleteUserToken(UserTokenInfoRespVO tokenInfo) {
|
|
|
|
+ // 删除令牌
|
|
|
|
+ // 删除相关缓存信息
|
|
|
|
+ String id = tokenInfo.getUserTokenId();
|
|
|
|
+ String pId = tokenInfo.getPid();
|
|
|
|
+ String tokenIdKey = getKeyPrefix(id, TokenTypeEnum.USER.getValue());
|
|
|
|
+ String openIdTokenIdKey = getKeyPrefix(pId, USER_OPEN_ID_TOKEN_ID_KEY_TYPE);
|
|
|
|
+ String openIdAppIdKey = getKeyPrefix(pId, USER_OPEN_ID_APP_ID_KEY_TYPE);
|
|
|
|
+ String[] keys = {tokenIdKey, openIdTokenIdKey, openIdAppIdKey};
|
|
|
|
+ stringRedisTemplate.delete(Arrays.asList(keys));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public UserTokenInfoRespVO getUserToken(String userTokenId) {
|
|
|
|
+ String key = getKeyPrefix(userTokenId, TokenTypeEnum.USER.getValue());
|
|
|
|
+ return getTokenInfo(key, UserTokenInfoRespVO.class);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public AppTokenInfoRespVO getAppToken(String appTokenId) {
|
|
|
|
+ String key = getKeyPrefix(appTokenId, TokenTypeEnum.APP.getValue());
|
|
|
|
+ return getTokenInfo(key, AppTokenInfoRespVO.class);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void renewAppToken(AppTokenInfoRespVO tokenInfo) {
|
|
|
|
+ cacheAppToken(tokenInfo);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void deleteAppToken(AppTokenInfoRespVO tokenInfo) {
|
|
|
|
+ stringRedisTemplate.delete(tokenInfo.getAppTokenId());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void cacheAppAuthResult(List<String> appIds, UserTokenInfoRespVO zeroTrustUserTokenInfoRespVO) {
|
|
|
|
+ if (CollectionUtils.isEmpty(appIds)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ String pId = zeroTrustUserTokenInfoRespVO.getPid();
|
|
|
|
+
|
|
|
|
+ // 应用鉴权成功后保存 openId-appIds到缓存中
|
|
|
|
+ long expireTime = (zeroTrustUserTokenInfoRespVO.getExpireAt().getTime() - System.currentTimeMillis()) / 1000;
|
|
|
|
+ String openIdAppIdsKey = getKeyPrefix(pId, USER_OPEN_ID_APP_ID_KEY_TYPE);
|
|
|
|
+ String collect = appIds.stream().sorted(String::compareTo).collect(Collectors.joining(StrUtil.COMMA));
|
|
|
|
+ // 拼接用户id
|
|
|
|
+ collect = String.join(StrUtil.UNDERLINE, pId, collect);
|
|
|
|
+ stringRedisTemplate
|
|
|
|
+ .opsForValue()
|
|
|
|
+ .set(openIdAppIdsKey, collect, expireTime, TimeUnit.SECONDS);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<AppAuthResultDto> getAppAuthResult(Collection<String> pIds) {
|
|
|
|
+ if (CollectionUtils.isEmpty(pIds)) {
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
+ }
|
|
|
|
+ List<String> userAuthKeys = pIds.stream()
|
|
|
|
+ .map(item -> getKeyPrefix(item, USER_OPEN_ID_APP_ID_KEY_TYPE))
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
+ List<String> appAuthObjs = stringRedisTemplate.opsForValue().multiGet(userAuthKeys);
|
|
|
|
+ return Optional.ofNullable(appAuthObjs)
|
|
|
|
+ .orElse(Collections.emptyList())
|
|
|
|
+ .stream()
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
+ .map(e -> {
|
|
|
|
+ String[] split = e.split(StrUtil.UNDERLINE);
|
|
|
|
+ AppAuthResultDto dto = new AppAuthResultDto();
|
|
|
|
+ dto.setOpenId(split[0]);
|
|
|
|
+ List<String> list = Arrays.asList(split[1].split(StrUtil.COMMA));
|
|
|
|
+ dto.setAppIds(list);
|
|
|
|
+ return dto;
|
|
|
|
+ })
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<String> getUserTokenIds(List<String> pIds) {
|
|
|
|
+ if (CollectionUtils.isEmpty(pIds)) {
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ List<String> tokenKeys = pIds.stream().map(item -> getKeyPrefix(item, USER_OPEN_ID_TOKEN_ID_KEY_TYPE))
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
+
|
|
|
|
+ List<String> userTokenList = stringRedisTemplate.opsForValue().multiGet(tokenKeys);
|
|
|
|
+
|
|
|
|
+ // 过滤出 null 的情况
|
|
|
|
+ return Optional.ofNullable(userTokenList).orElse(Collections.emptyList())
|
|
|
|
+ .stream()
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public Map<String, String> getUserTokenIdByOpenId(Collection<String> openIds) {
|
|
|
|
+ if (CollectionUtils.isEmpty(openIds)) {
|
|
|
|
+ return Collections.emptyMap();
|
|
|
|
+ }
|
|
|
|
+ ArrayList<String> openIdList = new ArrayList<>(openIds);
|
|
|
|
+ List<String> keys = openIdList.stream()
|
|
|
|
+ .map(e -> getKeyPrefix(e, USER_OPEN_ID_TOKEN_ID_KEY_TYPE))
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
+ List<String> userTokenIds = stringRedisTemplate.opsForValue().multiGet(keys);
|
|
|
|
+ if (CollectionUtils.isEmpty(userTokenIds)) {
|
|
|
|
+ return Collections.emptyMap();
|
|
|
|
+ }
|
|
|
|
+ Map<String, String> map = new HashMap<>();
|
|
|
|
+ for (int i = 0; i < keys.size(); i++) {
|
|
|
|
+ map.put(openIdList.get(i), userTokenIds.get(i));
|
|
|
|
+ }
|
|
|
|
+ return map;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void appTokenActionHandle(AppTokenInfoRespVO tokenInfo, String action) {
|
|
|
|
+ if (null == tokenInfo) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (TokenActionEnum.OFFLINE.getValue().equals(action)) {
|
|
|
|
+ deleteAppToken(tokenInfo);
|
|
|
|
+ } else if (TokenActionEnum.ONLINE.getValue().equals(action)) {
|
|
|
|
+ cacheAppToken(tokenInfo);
|
|
|
|
+ } else if (TokenActionEnum.RENEW.getValue().equals(action)) {
|
|
|
|
+ renewAppToken(tokenInfo);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void userTokenActionHandle(UserTokenInfoRespVO tokenInfo, String action) {
|
|
|
|
+ if (null == tokenInfo) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (TokenActionEnum.OFFLINE.getValue().equals(action)) {
|
|
|
|
+ deleteUserToken(tokenInfo);
|
|
|
|
+ } else if (TokenActionEnum.ONLINE.getValue().equals(action)) {
|
|
|
|
+ cacheUserToken(tokenInfo);
|
|
|
|
+ } else if (TokenActionEnum.RENEW.getValue().equals(action)) {
|
|
|
|
+ renewUserToken(tokenInfo);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ private <T> T getTokenInfo(String tokenId, Class<T> clazz) {
|
|
|
|
+ String tokenStr = stringRedisTemplate.opsForValue().get(tokenId);
|
|
|
|
+ if (StringUtils.isBlank(tokenStr)) {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ return JSON.parseObject(tokenStr, clazz);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ private String getKeyPrefix(String id, String tokenType) {
|
|
|
|
+ if (tokenType.equals(TokenTypeEnum.APP.getValue())) {
|
|
|
|
+ return AuthRedisConstant.REDIS_APP_TOKEN_NAMESPACE + id;
|
|
|
|
+ } else if (tokenType.equals(TokenTypeEnum.USER.getValue())) {
|
|
|
|
+ return AuthRedisConstant.REDIS_USER_TOKEN_NAMESPACE + id;
|
|
|
|
+ } else if (tokenType.equals(USER_OPEN_ID_TOKEN_ID_KEY_TYPE)) {
|
|
|
|
+ return AuthRedisConstant.REDIS_OPEN_ID_TOKEN_NAMESPACE + id;
|
|
|
|
+ } else if (tokenType.equals(USER_OPEN_ID_APP_ID_KEY_TYPE)) {
|
|
|
|
+ return AuthRedisConstant.REDIS_OPEN_AUTH_APP_ID_NAMESPACE + id;
|
|
|
|
+ } else {
|
|
|
|
+ throw new ApplicationException("不支持的类型");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|