|
@@ -1,16 +1,21 @@
|
|
package com.chelvc.framework.oauth.token;
|
|
package com.chelvc.framework.oauth.token;
|
|
|
|
|
|
-import java.time.Duration;
|
|
|
|
|
|
+import java.util.Collections;
|
|
|
|
+import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
+import java.util.stream.Stream;
|
|
|
|
|
|
import com.chelvc.framework.base.context.SessionContextHolder;
|
|
import com.chelvc.framework.base.context.SessionContextHolder;
|
|
|
|
+import com.chelvc.framework.common.model.Terminal;
|
|
import com.chelvc.framework.common.util.ObjectUtils;
|
|
import com.chelvc.framework.common.util.ObjectUtils;
|
|
import com.chelvc.framework.common.util.StringUtils;
|
|
import com.chelvc.framework.common.util.StringUtils;
|
|
import com.chelvc.framework.oauth.context.OAuthContextHolder;
|
|
import com.chelvc.framework.oauth.context.OAuthContextHolder;
|
|
import com.chelvc.framework.redis.context.RedisContextHolder;
|
|
import com.chelvc.framework.redis.context.RedisContextHolder;
|
|
-import com.google.common.collect.ImmutableMap;
|
|
|
|
import lombok.NonNull;
|
|
import lombok.NonNull;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
+import org.springframework.data.redis.core.script.DefaultRedisScript;
|
|
|
|
+import org.springframework.data.redis.core.script.RedisScript;
|
|
import org.springframework.security.core.userdetails.UserDetails;
|
|
import org.springframework.security.core.userdetails.UserDetails;
|
|
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
|
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
|
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
|
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
|
@@ -25,8 +30,26 @@ import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
|
|
*/
|
|
*/
|
|
@Slf4j
|
|
@Slf4j
|
|
public class RedisTokenStore extends JwtTokenStore {
|
|
public class RedisTokenStore extends JwtTokenStore {
|
|
|
|
+ /**
|
|
|
|
+ * 终端/令牌更新脚本映射表
|
|
|
|
+ */
|
|
|
|
+ private final Map<Terminal, RedisScript<Boolean>> scripts;
|
|
|
|
+
|
|
public RedisTokenStore(@NonNull JwtAccessTokenConverter jwtAccessTokenConverter) {
|
|
public RedisTokenStore(@NonNull JwtAccessTokenConverter jwtAccessTokenConverter) {
|
|
super(jwtAccessTokenConverter);
|
|
super(jwtAccessTokenConverter);
|
|
|
|
+
|
|
|
|
+ // 初始化各终端令牌更新脚本映射表
|
|
|
|
+ this.scripts = Stream.of(Terminal.values()).collect(Collectors.toMap(terminal -> terminal,
|
|
|
|
+ terminal -> new DefaultRedisScript<>(
|
|
|
|
+ String.format("return redis.call('HSET', KEYS[1], 'scope', ARGV[1], '%s', ARGV[2]) " +
|
|
|
|
+ "and redis.call('EXPIRE', KEYS[1], ARGV[3])", terminal), Boolean.class
|
|
|
|
+ )));
|
|
|
|
+
|
|
|
|
+ // 初始化无终端令牌更新脚本
|
|
|
|
+ this.scripts.put(null, new DefaultRedisScript<>(
|
|
|
|
+ "return redis.call('HSET', KEYS[1], 'scope', ARGV[1], 'null', ARGV[2]) " +
|
|
|
|
+ "and redis.call('EXPIRE', KEYS[1], ARGV[3])", Boolean.class
|
|
|
|
+ ));
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -35,15 +58,12 @@ public class RedisTokenStore extends JwtTokenStore {
|
|
if (principal instanceof UserDetails) {
|
|
if (principal instanceof UserDetails) {
|
|
principal = ((UserDetails) principal).getUsername();
|
|
principal = ((UserDetails) principal).getUsername();
|
|
}
|
|
}
|
|
- String key = OAuthContextHolder.key(principal);
|
|
|
|
|
|
+ List<String> keys = Collections.singletonList(OAuthContextHolder.key(principal));
|
|
String scope = ObjectUtils.ifNull(OAuthContextHolder.getScope(token), StringUtils.EMPTY);
|
|
String scope = ObjectUtils.ifNull(OAuthContextHolder.getScope(token), StringUtils.EMPTY);
|
|
- Map<String, ?> values = ImmutableMap.of(
|
|
|
|
- SessionContextHolder.HEADER_SCOPE, scope,
|
|
|
|
- String.valueOf(SessionContextHolder.getTerminal()), token.getValue()
|
|
|
|
- );
|
|
|
|
- Duration duration = RedisContextHolder.duration(token.getExpiration());
|
|
|
|
|
|
+ long duration = RedisContextHolder.duration(token.getExpiration()).getSeconds();
|
|
|
|
+ RedisScript<Boolean> script = this.scripts.get(SessionContextHolder.getTerminal());
|
|
try {
|
|
try {
|
|
- RedisContextHolder.put(RedisContextHolder.getDefaultTemplate(), key, values, duration);
|
|
|
|
|
|
+ RedisContextHolder.getDefaultTemplate().execute(script, keys, scope, token.getValue(), duration);
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
log.warn("Redis token save failed: {}", e.getMessage());
|
|
log.warn("Redis token save failed: {}", e.getMessage());
|
|
}
|
|
}
|