8月10 版本修改
This commit is contained in:
@@ -83,12 +83,6 @@ yh:
|
|||||||
mobi-api-pattern: /mobiapi/*
|
mobi-api-pattern: /mobiapi/*
|
||||||
app-auth:
|
app-auth:
|
||||||
enabled: true
|
enabled: true
|
||||||
# 本应用自身身份(客户端签名用,若 UserBase 需调用其他带签名服务)
|
|
||||||
app-key: 100616
|
|
||||||
app-secret: 1febb9502d2744b6a235d3e4cfde4a2d
|
|
||||||
# 受信应用(服务端验签用):appKey -> appSecret
|
|
||||||
trusted-apps:
|
|
||||||
100616: 1febb9502d2744b6a235d3e4cfde4a2d
|
|
||||||
|
|
||||||
ADMIN_TAG_ID: 290
|
ADMIN_TAG_ID: 290
|
||||||
|
|
||||||
|
|||||||
@@ -69,12 +69,6 @@ yh:
|
|||||||
mobi-api-pattern: /mobiapi/*
|
mobi-api-pattern: /mobiapi/*
|
||||||
app-auth:
|
app-auth:
|
||||||
enabled: true
|
enabled: true
|
||||||
# 本应用自身身份(客户端签名用,若 UserBase 需调用其他带签名服务)
|
|
||||||
app-key: 100616
|
|
||||||
app-secret: 1febb9502d2744b6a235d3e4cfde4a2d
|
|
||||||
# 受信应用(服务端验签用):appKey -> appSecret
|
|
||||||
trusted-apps:
|
|
||||||
100616: 1febb9502d2744b6a235d3e4cfde4a2d
|
|
||||||
|
|
||||||
ADMIN_TAG_ID: 290
|
ADMIN_TAG_ID: 290
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.yunhai.userbase.config;
|
|||||||
|
|
||||||
import com.yunhai.platform.appauth.AppAuthProperties;
|
import com.yunhai.platform.appauth.AppAuthProperties;
|
||||||
import com.yunhai.platform.appauth.AppSecretProvider;
|
import com.yunhai.platform.appauth.AppSecretProvider;
|
||||||
|
import com.yunhai.platform.appauth.LocalAppIdentityProvider;
|
||||||
import com.yunhai.userbase.repository.ApplicationInfoRepository;
|
import com.yunhai.userbase.repository.ApplicationInfoRepository;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -10,7 +11,9 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
* 用户中心验签密钥源:UserBase 作为密钥权威源,优先从本库 application_info 解析调用方密钥
|
* 用户中心验签密钥源:UserBase 作为密钥权威源,优先从本库 application_info 解析调用方密钥
|
||||||
* (覆盖全部「已颁发」应用),并以配置式 {@code yh.app-auth.trustedApps} 兜底平台自身默认密钥。
|
* (覆盖全部「已颁发」应用),并以配置式 {@code yh.app-auth.trustedApps} 兜底平台自身默认密钥。
|
||||||
* 显式覆盖 yh-app-auth 默认的 {@code @ConditionalOnMissingBean} 实现,使开放接口签名校验
|
* 显式覆盖 yh-app-auth 默认的 {@code @ConditionalOnMissingBean} 实现,使开放接口签名校验
|
||||||
* 不依赖 Redis 中 {@code sign:app:*} 的预填充时机,且能验签所有已颁发应用。
|
* 不依赖 Redis 中 {@code sign:app:*} 的预填充时机,且能验签所有已颁发应用。<br><br>
|
||||||
|
* 同时注册 UserBase 自身作为出站调用方的身份:固定 appKey=100000,密钥落库,不再依赖 yml
|
||||||
|
* 配置 app-key/app-secret。
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public class AppSecretConfig {
|
public class AppSecretConfig {
|
||||||
@@ -20,4 +23,9 @@ public class AppSecretConfig {
|
|||||||
AppAuthProperties properties) {
|
AppAuthProperties properties) {
|
||||||
return new UserBaseAppSecretProvider(repository, properties);
|
return new UserBaseAppSecretProvider(repository, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public LocalAppIdentityProvider localAppIdentityProvider(ApplicationInfoRepository repository) {
|
||||||
|
return new UserBaseLocalAppIdentityProvider(repository);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package com.yunhai.userbase.config;
|
||||||
|
|
||||||
|
import com.yunhai.platform.appauth.LocalAppIdentityProvider;
|
||||||
|
import com.yunhai.userbase.entity.ApplicationInfo;
|
||||||
|
import com.yunhai.userbase.repository.ApplicationInfoRepository;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UserBase 自身作为「出站签名调用方」的身份提供方。<br><br>
|
||||||
|
* 约定:<br>
|
||||||
|
* 1) appKey 固定占用 100000(基石应用段),由 application_bootstrap.sql 初始化脚本幂等插入;<br>
|
||||||
|
* 2) appSecret 从 application_info 表按 appKey=100000 读取,带 60s 本地缓存(密钥重设后 60s 内生效)。<br><br>
|
||||||
|
* 显式覆盖 yh-app-auth-spring-boot-starter 默认的 PropertyLocalAppIdentityProvider(yml 不再需要
|
||||||
|
* 配置 yh.app-auth.app-key / app-secret)。
|
||||||
|
*/
|
||||||
|
public class UserBaseLocalAppIdentityProvider implements LocalAppIdentityProvider {
|
||||||
|
|
||||||
|
private static final String USER_CENTER_APP_KEY = "100000";
|
||||||
|
private static final int USER_CENTER_APP_KEY_INT = 100000;
|
||||||
|
private static final long TTL_MS = 60_000L;
|
||||||
|
|
||||||
|
private final ApplicationInfoRepository repository;
|
||||||
|
private final ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public UserBaseLocalAppIdentityProvider(ApplicationInfoRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAppKey() {
|
||||||
|
return USER_CENTER_APP_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAppSecret() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
CacheEntry hit = cache.get(USER_CENTER_APP_KEY);
|
||||||
|
if (hit != null && now - hit.ts < TTL_MS) {
|
||||||
|
return hit.secret;
|
||||||
|
}
|
||||||
|
String secret = null;
|
||||||
|
try {
|
||||||
|
ApplicationInfo info = repository.findByAppKey(USER_CENTER_APP_KEY_INT);
|
||||||
|
if (info != null && info.getAppSecret() != null && !info.getAppSecret().trim().isEmpty()) {
|
||||||
|
secret = info.getAppSecret();
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
cache.put(USER_CENTER_APP_KEY, new CacheEntry(now, secret));
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class CacheEntry {
|
||||||
|
final long ts;
|
||||||
|
final String secret;
|
||||||
|
|
||||||
|
CacheEntry(long ts, String secret) {
|
||||||
|
this.ts = ts;
|
||||||
|
this.secret = secret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,29 @@
|
|||||||
package com.yunhai.userbase.controller.oapi;
|
package com.yunhai.userbase.controller.oapi;
|
||||||
|
|
||||||
|
import com.yunhai.platform.utils.model.BoaGroup;
|
||||||
|
import com.yunhai.platform.utils.model.BoaModule;
|
||||||
import com.yunhai.platform.utils.model.BoaUser;
|
import com.yunhai.platform.utils.model.BoaUser;
|
||||||
|
import com.yunhai.userbase.model.groupauthz.UserPermissionAppVo;
|
||||||
|
import com.yunhai.userbase.model.groupauthz.UserPermissionCategoryVo;
|
||||||
|
import com.yunhai.userbase.model.groupauthz.UserPermissionModuleVo;
|
||||||
|
import com.yunhai.userbase.service.IGroupAuthzService;
|
||||||
import com.yunhai.userbase.service.UserCenterService;
|
import com.yunhai.userbase.service.UserCenterService;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户中心开放接口:供其他业务服务经 yh-app-auth 签名调用({@code /open/api/user/...})。<br><br>
|
* 用户中心开放接口:供其他业务服务经 yh-app-auth 签名调用({@code /open/api/user/...})。<br><br>
|
||||||
* 路径与基础平台 {@code DefaultUserCenterClient} 硬编码的契约严格一致:
|
* 路径与基础平台 {@code DefaultUserCenterClient} 硬编码的契约严格一致:
|
||||||
* {@code GET /open/api/user/byId?id=}、{@code /byLoginName?loginName=}、{@code /byPhone?phone=}。<br>
|
* {@code GET /open/api/user/byId?id=}、{@code /byLoginName?loginName=}、{@code /byPhone?phone=}、
|
||||||
|
* {@code /open/api/user/modules?userId=&schId=}。<br>
|
||||||
* 接口本身不做验签——签名由 {@code OpenApiAuthEnforceConfiguration} 在过滤器层强制要求,
|
* 接口本身不做验签——签名由 {@code OpenApiAuthEnforceConfiguration} 在过滤器层强制要求,
|
||||||
* 未带 {@code X-App-Key/X-Timestamp/X-Signature} 的请求直接 401。
|
* 未带 {@code X-App-Key/X-Timestamp/X-Signature} 的请求直接 401。
|
||||||
*/
|
*/
|
||||||
@@ -22,6 +34,9 @@ public class OpenBaseController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private UserCenterService userCenterService;
|
private UserCenterService userCenterService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IGroupAuthzService groupAuthzService;
|
||||||
|
|
||||||
@GetMapping("byId")
|
@GetMapping("byId")
|
||||||
public BoaUser byId(@RequestParam("id") Integer id) {
|
public BoaUser byId(@RequestParam("id") Integer id) {
|
||||||
return userCenterService.getUserInfoWithDeptById(id);
|
return userCenterService.getUserInfoWithDeptById(id);
|
||||||
@@ -42,4 +57,78 @@ public class OpenBaseController {
|
|||||||
}
|
}
|
||||||
return userCenterService.getUserInfoWithDeptByPhone(phone);
|
return userCenterService.getUserInfoWithDeptByPhone(phone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户在指定学校下的已授权模块列表。<br>
|
||||||
|
* 若 {@code schId} 为 null 时,自动取用户的主学校;若仍无主学校信息,退化为取用户主归属组(groups 第 0 个)。
|
||||||
|
*
|
||||||
|
* @param userId 用户ID(必填)
|
||||||
|
* @param schId 学校ID/组ID(可选;为 null 时按上述规则推断)
|
||||||
|
* @return 扁平化的已授权模块列表(含基础平台统一 BoaModule 模型);无权限时返回空列表
|
||||||
|
*/
|
||||||
|
@GetMapping("modules")
|
||||||
|
public List<BoaModule> modules(@RequestParam("userId") Integer userId,
|
||||||
|
@RequestParam(value = "schId", required = false) Integer schId) {
|
||||||
|
if (userId == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
Integer effectiveGroupId = resolveEffectiveGroupId(userId, schId);
|
||||||
|
if (effectiveGroupId == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
List<UserPermissionCategoryVo> tree = groupAuthzService.findUserPermissionTree(effectiveGroupId, userId);
|
||||||
|
if (tree == null || tree.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
List<BoaModule> result = new ArrayList<>();
|
||||||
|
for (UserPermissionCategoryVo category : tree) {
|
||||||
|
if (category.getApps() == null) continue;
|
||||||
|
for (UserPermissionAppVo appVo : category.getApps()) {
|
||||||
|
String icon = appVo.getPcIcon();
|
||||||
|
collectModules(appVo.getModules(), icon, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归收集已授权模块树到扁平列表,并把应用 PC 图标作为模块的 icon 兜底(BoaModule.icon)。
|
||||||
|
*/
|
||||||
|
private void collectModules(List<UserPermissionModuleVo> modules,
|
||||||
|
String appIcon,
|
||||||
|
List<BoaModule> collector) {
|
||||||
|
if (modules == null || modules.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (UserPermissionModuleVo m : modules) {
|
||||||
|
BoaModule bm = new BoaModule();
|
||||||
|
BeanUtils.copyProperties(m, bm);
|
||||||
|
bm.setIcon(appIcon);
|
||||||
|
collector.add(bm);
|
||||||
|
collectModules(m.getChildren(), appIcon, collector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按「schId 为空时」解析出用户主学校/主组作为模块查询的上下文组ID。
|
||||||
|
*/
|
||||||
|
private Integer resolveEffectiveGroupId(Integer userId, Integer schId) {
|
||||||
|
if (schId != null) {
|
||||||
|
return schId;
|
||||||
|
}
|
||||||
|
BoaUser boa = userCenterService.getUserInfoWithDeptById(userId);
|
||||||
|
if (boa == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BoaGroup school = boa.getSchool();
|
||||||
|
if (school != null && school.getId() != null) {
|
||||||
|
return school.getId();
|
||||||
|
}
|
||||||
|
List<BoaGroup> groups = boa.getGroups();
|
||||||
|
if (groups != null && !groups.isEmpty()) {
|
||||||
|
BoaGroup main = groups.get(0);
|
||||||
|
return main == null ? null : main.getId();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ import java.util.List;
|
|||||||
* @description
|
* @description
|
||||||
*/
|
*/
|
||||||
public interface ApplicationInfoRepository extends JpaRepository<ApplicationInfo, Integer>, JpaSpecificationExecutor<ApplicationInfo> {
|
public interface ApplicationInfoRepository extends JpaRepository<ApplicationInfo, Integer>, JpaSpecificationExecutor<ApplicationInfo> {
|
||||||
Integer countByCategoryId(Integer id);
|
@Query("SELECT COUNT(a.id) FROM ApplicationInfo a WHERE a.categoryId = :categoryId AND a.appKey > 100000")
|
||||||
|
Integer countByCategoryId(@Param("categoryId") Integer id);
|
||||||
|
|
||||||
boolean existsByName(String name);
|
boolean existsByName(String name);
|
||||||
|
|
||||||
@@ -54,21 +55,23 @@ public interface ApplicationInfoRepository extends JpaRepository<ApplicationInf
|
|||||||
/**
|
/**
|
||||||
* 按应用类型查询排序所需的精简视图(仅 id/name/sortNo),不分页。<br>
|
* 按应用类型查询排序所需的精简视图(仅 id/name/sortNo),不分页。<br>
|
||||||
* 使用构造器表达式做 DTO 投影,避免加载整个实体(含 appSecret、各类 URL 等无关大字段)。<br>
|
* 使用构造器表达式做 DTO 投影,避免加载整个实体(含 appSecret、各类 URL 等无关大字段)。<br>
|
||||||
|
* 排除用户中心自身的基石应用(appKey=100000)。
|
||||||
*
|
*
|
||||||
* @param categoryId 应用类型ID
|
* @param categoryId 应用类型ID
|
||||||
* @return 该类型下全部应用的排序视图,按 sortNo 升序(未排序排末尾),id 升序兜底
|
* @return 该类型下全部应用的排序视图,按 sortNo 升序(未排序排末尾),id 升序兜底
|
||||||
*/
|
*/
|
||||||
@Query("SELECT new com.yunhai.userbase.model.application.ApplicationInfoSortVo(a.id, a.name, a.sortNo) " +
|
@Query("SELECT new com.yunhai.userbase.model.application.ApplicationInfoSortVo(a.id, a.name, a.sortNo) " +
|
||||||
"FROM ApplicationInfo a WHERE a.categoryId = :categoryId ORDER BY a.sortNo ASC, a.id ASC")
|
"FROM ApplicationInfo a WHERE a.categoryId = :categoryId AND a.appKey > 100000 ORDER BY a.sortNo ASC, a.id ASC")
|
||||||
List<ApplicationInfoSortVo> findSortVoByCategoryId(@Param("categoryId") Integer categoryId);
|
List<ApplicationInfoSortVo> findSortVoByCategoryId(@Param("categoryId") Integer categoryId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用授权用:查询全部应用的扁平投影(含 categoryId 供按类型分组),仅取 id/name/pcIcon。<br>
|
* 应用授权用:查询全部应用的扁平投影(含 categoryId 供按类型分组),仅取 id/name/pcIcon。<br>
|
||||||
* 按 categoryId、sortNo、id 升序,便于分组后同类型内保持排序。<br>
|
* 按 categoryId、sortNo、id 升序,便于分组后同类型内保持排序。<br>
|
||||||
|
* 排除用户中心自身的基石应用(appKey=100000)。
|
||||||
*
|
*
|
||||||
* @return 全部应用的授权投影行
|
* @return 全部应用的授权投影行
|
||||||
*/
|
*/
|
||||||
@Query("SELECT new com.yunhai.userbase.model.appauthz.AppAuthzAppRow(a.categoryId, a.id, a.name, a.pcIcon) " +
|
@Query("SELECT new com.yunhai.userbase.model.appauthz.AppAuthzAppRow(a.categoryId, a.id, a.name, a.pcIcon) " +
|
||||||
"FROM ApplicationInfo a ORDER BY a.categoryId ASC, a.sortNo ASC, a.id ASC")
|
"FROM ApplicationInfo a WHERE a.appKey > 100000 ORDER BY a.categoryId ASC, a.sortNo ASC, a.id ASC")
|
||||||
List<AppAuthzAppRow> findAllAuthzRows();
|
List<AppAuthzAppRow> findAllAuthzRows();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ public class ApplicationInfoService implements IApplicationInfoService {
|
|||||||
@Override
|
@Override
|
||||||
public Predicate toPredicate(Root<ApplicationInfo> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
|
public Predicate toPredicate(Root<ApplicationInfo> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
|
||||||
List<Predicate> predicates = new ArrayList<Predicate>();
|
List<Predicate> predicates = new ArrayList<Predicate>();
|
||||||
|
predicates.add(cb.greaterThan(root.get("appKey"), 100000));
|
||||||
if (query != null) {
|
if (query != null) {
|
||||||
if (StringUtils.isNotEmpty(query.getName())) {
|
if (StringUtils.isNotEmpty(query.getName())) {
|
||||||
String keyword = query.getName();
|
String keyword = query.getName();
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ spring:
|
|||||||
simple:
|
simple:
|
||||||
auto-startup: false
|
auto-startup: false
|
||||||
|
|
||||||
|
|
||||||
# 单点登录 / 应用间签名鉴权(基础平台 yh-auth / yh-app-auth)
|
# 单点登录 / 应用间签名鉴权(基础平台 yh-auth / yh-app-auth)
|
||||||
yh:
|
yh:
|
||||||
sso:
|
sso:
|
||||||
@@ -69,12 +68,6 @@ yh:
|
|||||||
mobi-api-pattern: /mobiapi/*
|
mobi-api-pattern: /mobiapi/*
|
||||||
app-auth:
|
app-auth:
|
||||||
enabled: true
|
enabled: true
|
||||||
# 本应用自身身份(客户端签名用,若 UserBase 需调用其他带签名服务)
|
|
||||||
app-key: 100616
|
|
||||||
app-secret: 1febb9502d2744b6a235d3e4cfde4a2d
|
|
||||||
# 受信应用(服务端验签用):appKey -> appSecret
|
|
||||||
trusted-apps:
|
|
||||||
100616: 1febb9502d2744b6a235d3e4cfde4a2d
|
|
||||||
|
|
||||||
ADMIN_TAG_ID: 290
|
ADMIN_TAG_ID: 290
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
-- ============================================================
|
||||||
|
-- 用户中心自身应用身份初始化(appKey=100000,后续业务应用从 100001 起)
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
-- 适用数据库:MySQL 5.7 / 8.0
|
||||||
|
-- 运行方式:
|
||||||
|
-- mysql --default-character-set=utf8mb4 -u<user> -p<password> <db_name> < application_bootstrap.sql
|
||||||
|
-- 前置:表结构由 Hibernate(ddl-auto=update)创建,请先启动一次应用生成
|
||||||
|
-- application_info 表后再执行本脚本;如已执行请忽略(幂等)。
|
||||||
|
-- 说明:
|
||||||
|
-- 1. 本脚本按 app_key=100000 做幂等判断,重复执行不会新增重复记录。
|
||||||
|
-- 2. 用户中心作为「应用平台基石/默认调用方」,自身也需要一个合法的应用身份,
|
||||||
|
-- 用于对外发起 yh-app-auth 签名的应用签名请求;因此固定占用 appKey=100000。
|
||||||
|
-- 3. appSecret 每次执行脚本若不存在时会重新生成一个 UUID(32 位十六进制);
|
||||||
|
-- 已存在记录不会被修改,生产上如需重置请手动 UPDATE 或在应用管理界面点「重设密钥」。
|
||||||
|
-- 4. 业务应用新增时 ApplicationInfoService 会按 MAX(app_key)+1 分配:
|
||||||
|
-- 因此本脚本写入 100000 后,下一条业务应用 appKey=100001,与预期一致。
|
||||||
|
-- 5. AUTO_INCREMENT=100001 仅设置 application_info 表的主键 id(非 appKey),
|
||||||
|
-- 使后续新建行的主键 id 也从 100001 起,与 appKey 段对齐,便于排查。
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
-- 1) 插入用户中心自身身份(appKey=100000),已存在则跳过
|
||||||
|
INSERT INTO application_info (app_key, name, app_secret, app_desc, create_user, create_time, update_user, update_time)
|
||||||
|
SELECT 100000,
|
||||||
|
'用户中心平台',
|
||||||
|
REPLACE(UUID(), '-', ''),
|
||||||
|
'用户中心自身应用身份(基石应用,不对外展示于应用管理列表)',
|
||||||
|
0,
|
||||||
|
NOW(),
|
||||||
|
0,
|
||||||
|
NOW()
|
||||||
|
FROM DUAL
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM application_info WHERE app_key = 100000);
|
||||||
|
|
||||||
|
-- 2) 调整主键 id 自增起点,使其与 appKey 段对齐(100001 起)
|
||||||
|
ALTER TABLE application_info AUTO_INCREMENT = 100001;
|
||||||
Reference in New Issue
Block a user