init: UserBaseService (backend + deploy + scripts)
ci-userbase-service / build-and-push (push) Successful in 40s

This commit is contained in:
chenxing
2026-08-10 14:50:22 +08:00
commit 4ec19486e0
234 changed files with 15604 additions and 0 deletions
@@ -0,0 +1,79 @@
package com.yunhai.userbase.config;
import com.yunhai.platform.appauth.AppAuthProperties;
import com.yunhai.platform.appauth.AppSecretProvider;
import com.yunhai.userbase.entity.ApplicationInfo;
import com.yunhai.userbase.repository.ApplicationInfoRepository;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* UserBase 作为「应用密钥权威源」的验签密钥提供方。<br><br>
* 解析优先级:<br>
* 1) 本库 application_info —— 覆盖全部「已颁发」应用,新增/重置密钥后即时生效;<br>
* 2) 配置式受信应用 {@code yh.app-auth.trusted-apps} —— 平台自身默认密钥(如 应用中心 100616)
* 兜底,使其即便尚未落库也可验签,避免「默认 appKey 未建行」导致验签失败。<br><br>
* 带 60s 本地 TTL 缓存,避免每次验签直打库(密钥变更最长 60s 后生效)。<br><br>
* 这样 UserBase 作为颁发方不依赖 Redis 预热、也不局限于 trustedApps 写死的少量密钥,
* 能够验签所有它已颁发的应用。
*/
public class UserBaseAppSecretProvider implements AppSecretProvider {
private final ApplicationInfoRepository repository;
private final Map<String, String> trustedApps;
private final ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();
private static final long TTL_MS = 60_000L;
public UserBaseAppSecretProvider(ApplicationInfoRepository repository, AppAuthProperties properties) {
this.repository = repository;
this.trustedApps = properties.getTrustedApps();
}
@Override
public String getSecret(String appKey) {
if (appKey == null) {
return null;
}
long now = System.currentTimeMillis();
CacheEntry hit = cache.get(appKey);
if (hit != null && now - hit.ts < TTL_MS) {
return hit.secret;
}
String secret = null;
try {
Integer id = parse(appKey);
if (id != null) {
ApplicationInfo info = repository.findByAppKey(id);
if (info != null && info.getAppSecret() != null && !info.getAppSecret().trim().isEmpty()) {
secret = info.getAppSecret();
}
}
} catch (Exception ignored) {
// 查询异常不阻断,继续走配置兜底
}
if (secret == null) {
secret = trustedApps.get(appKey);
}
cache.put(appKey, new CacheEntry(now, secret));
return secret;
}
private static Integer parse(String appKey) {
try {
return Integer.parseInt(appKey.trim());
} catch (NumberFormatException e) {
return null;
}
}
private static final class CacheEntry {
final long ts;
final String secret;
CacheEntry(long ts, String secret) {
this.ts = ts;
this.secret = secret;
}
}
}