新增网关和服务灰度能力

This commit is contained in:
gaoqr
2025-04-07 10:38:19 +08:00
parent acd3b2b16d
commit f5cab8d1d2
10 changed files with 54 additions and 30 deletions
@@ -59,4 +59,9 @@ public class LoginUser {
* 部门编号 * 部门编号
*/ */
private Long deptId; private Long deptId;
/**
* 灰度版本号
*/
private String grayVersion;
} }
@@ -150,7 +150,7 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
.setOrganId(tokenInfo.getOrganId()).setScopes(tokenInfo.getScopes()) .setOrganId(tokenInfo.getOrganId()).setScopes(tokenInfo.getScopes())
.setLarge(tokenInfo.getLarge()).setDbNo(tokenInfo.getDbNo()).setTableNo(tokenInfo.getTableNo()) .setLarge(tokenInfo.getLarge()).setDbNo(tokenInfo.getDbNo()).setTableNo(tokenInfo.getTableNo())
.setDataCode(tokenInfo.getDataCode()).setIsSupAdmin(tokenInfo.getIsSupAdmin()) .setDataCode(tokenInfo.getDataCode()).setIsSupAdmin(tokenInfo.getIsSupAdmin())
.setNickname(tokenInfo.getNickname()).setDeptId(tokenInfo.getDeptId()); .setNickname(tokenInfo.getNickname()).setDeptId(tokenInfo.getDeptId()).setGrayVersion(tokenInfo.getGrayVersion());
} }
@Override @Override
@@ -29,6 +29,8 @@ public class SecurityFrameworkUtils {
private static final String LOGIN_USER_HEADER = "login-user"; private static final String LOGIN_USER_HEADER = "login-user";
private static final String LOGIN_USER_GRAY_VERSION = "version";
private static final String LOGIN_USER_ID_ATTR = "login-user-id"; private static final String LOGIN_USER_ID_ATTR = "login-user-id";
private static final String LOGIN_USER_TYPE_ATTR = "login-user-type"; private static final String LOGIN_USER_TYPE_ATTR = "login-user-type";
private static final String DATA_CODE = "data-code"; private static final String DATA_CODE = "data-code";
@@ -122,6 +124,11 @@ public class SecurityFrameworkUtils {
} }
builder.header(DATA_CODE, user.getDataCode()); builder.header(DATA_CODE, user.getDataCode());
builder.header(ORGAN_ID, user.getOrganId().toString()); builder.header(ORGAN_ID, user.getOrganId().toString());
// 灰度版本号设置到headers,继续往下filter选择实例
String grayVersion = user.getGrayVersion();
if (StringUtils.hasText(grayVersion)) {
builder.header(LOGIN_USER_GRAY_VERSION, grayVersion);
}
} }
public static void setOrganHeader(ServerHttpRequest.Builder builder, LoginUser user) { public static void setOrganHeader(ServerHttpRequest.Builder builder, LoginUser user) {
@@ -37,4 +37,7 @@ public class OAuth2AccessTokenCheckRespDTO implements Serializable {
@Schema(description = "部门编号", example = "1") @Schema(description = "部门编号", example = "1")
private Long deptId; private Long deptId;
@Schema(description = "灰度版本号", example = "1")
private String grayVersion;
} }
@@ -94,6 +94,15 @@ public class OAuth2AccessTokenDO extends BaseDO {
*/ */
private Boolean isSupAdmin; private Boolean isSupAdmin;
/**
* 部门id
*/
@TableField(exist = false) @TableField(exist = false)
private Long deptId; private Long deptId;
/**
* 灰度版本号
*/
@TableField(exist = false)
private String grayVersion;
} }
@@ -147,4 +147,9 @@ public class OrganizationDO extends BaseDO {
* 纬度 * 纬度
*/ */
private String latitude; private String latitude;
/**
* 灰度版本号
*/
private String grayVersion;
} }
@@ -106,4 +106,9 @@ public class AdminUserDO extends OrganBaseDO {
*/ */
private String pinyinFull; private String pinyinFull;
/**
* 灰度版本号
*/
@TableField(exist = false)
private String grayVersion;
} }
@@ -1,6 +1,5 @@
package com.cf.imes.module.system.dal.redis.oauth2; package com.cf.imes.module.system.dal.redis.oauth2;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.cf.imes.framework.common.util.collection.CollectionUtils; import com.cf.imes.framework.common.util.collection.CollectionUtils;
import com.cf.imes.framework.common.util.json.JsonUtils; import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
@@ -11,8 +10,6 @@ import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -55,11 +52,9 @@ public class OAuth2AccessTokenRedisDAO {
String redisKey = formatKey(accessTokenDO.getAccessToken()); String redisKey = formatKey(accessTokenDO.getAccessToken());
// 清理多余字段,避免缓存 // 清理多余字段,避免缓存
accessTokenDO.setUpdater(null).setUpdateTime(null).setCreateTime(null).setCreator(null).setDeleted(null); accessTokenDO.setUpdater(null).setUpdateTime(null).setCreateTime(null).setCreator(null).setDeleted(null);
long time = LocalDateTimeUtil.between(LocalDateTime.now(), accessTokenDO.getExpiresTime(), ChronoUnit.SECONDS); // 创建有效期1天的token
if (time > 0) { String jsonString = JsonUtils.toJsonString(accessTokenDO);
String jsonString = JsonUtils.toJsonString(accessTokenDO); stringRedisTemplate.opsForValue().set(redisKey, jsonString, 1, TimeUnit.DAYS);
stringRedisTemplate.opsForValue().set(redisKey, jsonString, time, TimeUnit.SECONDS);
}
} }
/** /**
@@ -141,6 +141,8 @@ public class AdminAuthServiceImpl implements AdminAuthService {
if (StringUtils.isBlank(dataSourceCode)) { if (StringUtils.isBlank(dataSourceCode)) {
throw exception(ORGAN_DATA_CODE_NOT_EXISTS); throw exception(ORGAN_DATA_CODE_NOT_EXISTS);
} }
// 机构的灰度版本设置到user
user.setGrayVersion(organ.getGrayVersion());
// 创建 Token 令牌,记录登录日志 // 创建 Token 令牌,记录登录日志
return createTokenAfterLoginSuccess(user, reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME, dataSourceCode); return createTokenAfterLoginSuccess(user, reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME, dataSourceCode);
} }
@@ -86,16 +86,15 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
OAuth2AccessTokenDO refreshTokenDO = createOAuth2ReToken(userId, userType, clientDO, scopes, large, dbNo, tableNo, dataCode, organId, nickname); OAuth2AccessTokenDO refreshTokenDO = createOAuth2ReToken(userId, userType, clientDO, scopes, large, dbNo, tableNo, dataCode, organId, nickname);
// 创建访问令牌 // 创建访问令牌
return createOAuth2AccessToken(refreshTokenDO, clientDO); return createOAuth2AccessToken(refreshTokenDO);
} }
@Override @Override
public OAuth2AccessTokenDO createAccessToken(AdminUserDO user, Integer userType, String clientId, String dataCode) { public OAuth2AccessTokenDO createAccessToken(AdminUserDO user, Integer userType, String clientId, String dataCode) {
OAuth2ClientDO clientDO = oauth2ClientService.validOAuthClientFromCache(clientId);
// 填入访问令牌包含的字段 // 填入访问令牌包含的字段
OAuth2AccessTokenDO refreshTokenDO = createOAuth2ReToken(user, userType, clientDO, dataCode); OAuth2AccessTokenDO refreshTokenDO = createOAuth2ReToken(user, userType, dataCode);
// 创建访问令牌 // 创建访问令牌
return createOAuth2AccessToken(refreshTokenDO, clientDO); return createOAuth2AccessToken(refreshTokenDO);
} }
@Override @Override
@@ -214,15 +213,17 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
} }
// 填入访问令牌包含的字段 // 填入访问令牌包含的字段
private OAuth2AccessTokenDO createOAuth2ReToken(AdminUserDO user, Integer userType, OAuth2ClientDO clientDO, String dataCode) { private OAuth2AccessTokenDO createOAuth2ReToken(AdminUserDO user, Integer userType, String dataCode) {
Long organId = user.getOrganId(); Long organId = user.getOrganId();
Long userId = user.getId(); Long userId = user.getId();
OAuth2AccessTokenDO refreshToken = new OAuth2AccessTokenDO().setRefreshToken(generateRefreshToken()) OAuth2AccessTokenDO refreshToken = new OAuth2AccessTokenDO()
.setUserId(userId).setUserType(userType) .setUserId(userId)
.setClientId(clientDO.getClientId()) .setUserType(userType)
.setExpiresTime(LocalDateTime.now().plusSeconds(clientDO.getRefreshTokenValiditySeconds()))
.setDataCode(dataCode) .setDataCode(dataCode)
.setOrganId(organId).setNickname(user.getNickname()).setDeptId(user.getDeptId()); .setOrganId(organId)
.setNickname(user.getNickname())
.setDeptId(user.getDeptId())
.setGrayVersion(user.getGrayVersion());
if (organId != null) { if (organId != null) {
OrganContextHolder.setOrganId(organId); OrganContextHolder.setOrganId(organId);
} }
@@ -232,18 +233,10 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
} }
// 在Redis中新增Token,除去刷新Token字段 // 在Redis中新增Token,除去刷新Token字段
private OAuth2AccessTokenDO createOAuth2AccessToken(OAuth2AccessTokenDO refreshTokenDO, OAuth2ClientDO clientDO) { private OAuth2AccessTokenDO createOAuth2AccessToken(OAuth2AccessTokenDO accessTokenDO) {
String currentToken = generateAccessToken(); String currentToken = generateAccessToken();
Long userId = refreshTokenDO.getUserId(); Long userId = accessTokenDO.getUserId();
OAuth2AccessTokenDO accessTokenDO = new OAuth2AccessTokenDO().setAccessToken(currentToken) accessTokenDO.setAccessToken(currentToken);
.setUserId(userId).setUserType(refreshTokenDO.getUserType())
.setClientId(clientDO.getClientId()).setScopes(refreshTokenDO.getScopes())
.setRefreshToken(refreshTokenDO.getRefreshToken())
.setExpiresTime(LocalDateTime.now().plusSeconds(clientDO.getAccessTokenValiditySeconds()))
.setLarge(refreshTokenDO.getLarge()).setDbNo(refreshTokenDO.getDbNo()).setTableNo(refreshTokenDO.getTableNo())
.setDataCode(refreshTokenDO.getDataCode()).setOrganId(refreshTokenDO.getOrganId())
.setNickname(refreshTokenDO.getNickname()).setIsSupAdmin(refreshTokenDO.getIsSupAdmin())
.setDeptId(refreshTokenDO.getDeptId());
// 记录到 Redis 中 // 记录到 Redis 中
oauth2AccessTokenRedisDAO.set(accessTokenDO); oauth2AccessTokenRedisDAO.set(accessTokenDO);
// 异步踢出其他token // 异步踢出其他token