net.guerlab.cloud.auth.factory.AbstractStringValueTokenFactory Maven / Gradle / Ivy
/*
* Copyright 2018-2025 guerlab.net and other contributors.
*
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.gnu.org/licenses/lgpl-3.0.html
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.guerlab.cloud.auth.factory;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import net.guerlab.cloud.auth.domain.TokenInfo;
import net.guerlab.cloud.auth.enums.TokenType;
import net.guerlab.cloud.auth.properties.StringValueTokenFactoryProperties;
/**
* 抽象字符串类型值 token工厂.
*
* @param 数据实体类型
* @param 配置类型
* @author guer
*/
public abstract class AbstractStringValueTokenFactory
extends AbstractTokenFactory {
/**
* 有效期关键字.
*/
protected static final String EXPIRATION_KEY = "exp";
/**
* 起始日期关键字.
*/
protected static final String NOT_BEFORE_KEY = "nbf";
/**
* KV连接器.
*/
protected static final String KV_CONNECTORS = ":";
/**
* 分组连接器.
*/
protected static final String GROUP_CONNECTORS = "&";
protected AbstractStringValueTokenFactory(P properties) {
super(properties);
}
/**
* 构造token.
*
* @param prefix 前缀
* @param data 数据
* @param expire 过期时间
* @param key 密钥
* @return token信息
*/
private TokenInfo build(String prefix, Map data, long expire, String key) {
long nowMillis = System.currentTimeMillis();
Date exp = null;
LocalDateTime expireAt = null;
// 添加Token过期时间
if (expire >= 0) {
exp = new Date(nowMillis + expire);
expireAt = LocalDateTime.ofInstant(exp.toInstant(), ZoneId.systemDefault());
data.put(EXPIRATION_KEY, String.valueOf(nowMillis + expire));
data.put(NOT_BEFORE_KEY, String.valueOf(nowMillis));
}
String dataString = data.entrySet().stream().map(entry -> entry.getKey() + KV_CONNECTORS + entry.getValue())
.collect(Collectors.joining(GROUP_CONNECTORS));
TokenInfo tokenInfo = new TokenInfo();
tokenInfo.setExpire(exp == null ? -1 : expire);
tokenInfo.setToken(prefix + buildToken(dataString, key, expire));
if (expireAt != null) {
tokenInfo.setExpireAt(expireAt);
}
return tokenInfo;
}
/**
* 构造token.
*
* @param dataString 数据字符串
* @param key 密钥
* @param expire 过期时间
* @return token
*/
protected abstract String buildToken(String dataString, String key, long expire);
/**
* 解析token.
*
* @param token token
* @param key 密钥
* @param tokenType 令牌类型
* @return 数据
*/
private Map parserToken(String token, String key, TokenType tokenType) {
String dataString = parseDataString(token, key);
if (StringUtils.isBlank(dataString)) {
throw tokenType.invalidException();
}
Map data = new HashMap<>(8);
for (String entry : dataString.split(GROUP_CONNECTORS)) {
String[] keyValues = entry.split(KV_CONNECTORS);
if (keyValues.length != 2) {
continue;
}
data.put(keyValues[0], keyValues[1]);
}
long now = System.currentTimeMillis();
if (data.containsKey(EXPIRATION_KEY)) {
try {
if (now > Long.parseLong(data.get(EXPIRATION_KEY))) {
throw tokenType.expiredException();
}
}
catch (Exception e) {
throw tokenType.expiredException();
}
}
if (data.containsKey(NOT_BEFORE_KEY)) {
try {
if (now < Long.parseLong(data.get(NOT_BEFORE_KEY))) {
throw tokenType.expiredException();
}
}
catch (Exception e) {
throw tokenType.expiredException();
}
}
data.remove(EXPIRATION_KEY);
data.remove(NOT_BEFORE_KEY);
return data;
}
/**
* 解析数据字符串.
*
* @param token token
* @param key 密钥
* @return 数据字符串
*/
@Nullable
protected abstract String parseDataString(String token, String key);
@Override
public final TokenInfo generateByAccessToken(T entity) {
Map data = new HashMap<>(8);
generateToken0(data, entity);
return build(getAccessTokenPrefix(), data, properties.getAccessTokenExpire(), properties.getAccessTokenKey());
}
@Override
public final TokenInfo generateByRefreshToken(T entity) {
Map data = new HashMap<>(8);
generateToken0(data, entity);
return build(getRefreshTokenPrefix(), data, properties.getRefreshTokenExpire(),
properties.getRefreshTokenKey());
}
@Override
public final T parseByAccessToken(String token) {
String accessToken = token.substring(getAccessTokenPrefix().length());
Map body = parserToken(accessToken, properties.getAccessTokenKey(), TokenType.ACCESS_TOKEN);
return parse0(body);
}
@Override
public final T parseByRefreshToken(String token) {
String refreshToken = token.substring(getRefreshTokenPrefix().length());
Map body = parserToken(refreshToken, properties.getRefreshTokenKey(), TokenType.REFRESH_TOKEN);
return parse0(body);
}
/**
* 解析token.
*
* @param body token内容
* @return 实体
*/
protected abstract T parse0(Map body);
/**
* 构建token.
*
* @param data data
* @param entity 实体
*/
protected abstract void generateToken0(Map data, T entity);
}