refactor(system/client): 优化客户端配置代码

This commit is contained in:
2025-11-25 22:07:50 +08:00
parent 0ab31ba9f9
commit 9776dfbf31
9 changed files with 121 additions and 119 deletions

View File

@@ -238,17 +238,23 @@ sa-token:
token-name: Authorization
# 是否启用动态 activeTimeout 功能
dynamic-active-timeout: true
## 提示:请通过页面功能 [系统管理/系统配置/客户端配置] 动态调整 timeout、active-timeout 配置项
## 如果不需要动态配置,请将 dynamic-active-timeout 设为 false并取消下方 timeout 和 active-timeout 配置注释,最好再移除相关登录处理代码
## 提示:请通过页面功能 [系统管理/系统配置/客户端配置] 动态调整下方注释的配置项
## 如果不需要动态配置,请取消下方配置注释,再移除相关登录处理代码
# # Token 有效期(单位:秒,默认 30 天,-1 代表永不过期)
# timeout: 86400
# # Token 最低活跃频率(单位:秒,默认 -1代表不限制永不冻结。如果 token 超过此时间没有访问系统就会被冻结)
# active-timeout: 1800
# 是否打开自动续签(如果此值为 true框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
auto-renew: true
# 是否允许同一账号多地同时登录(true 时允许一起登录,为 false新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个 Token为 true 时所有登录共用一个 Token为 false 时每次登录新建一个 Token
# # 是否打开自动续签(true每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
# auto-renew: true
# # 是否允许同一账号多地同时登录true:允许;false新登录挤掉旧登录)
# is-concurrent: true
# # 顶人下线的范围ALL_DEVICE_TYPE所有设备类型端
# replaced-range: ALL_DEVICE_TYPE
# # 同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)
# max-login-count: -1
# # 溢出人数的下线方式KICKOUT踢人下线
# overflow-logout-mode: KICKOUT
# 在多人登录同一账号时,是否共用一个 Tokentrue所有登录共用一个 Tokenfalse每次登录新建一个 Token
# 使用 jwt-simple 模式后is-share 恒等于 false目前本项目使用 jwt-simple 模式,可通过 sa-token.extension.enableJwt: false 关闭并自行提供 StpLogic 配置)
is-share: false
# 是否输出操作日志

View File

@@ -345,8 +345,12 @@ CREATE TABLE IF NOT EXISTS `sys_client` (
`client_id` varchar(50) NOT NULL COMMENT '客户端ID',
`client_type` varchar(50) NOT NULL COMMENT '客户端类型',
`auth_type` json NOT NULL COMMENT '认证类型',
`active_timeout` bigint(20) DEFAULT -1 COMMENT 'Token最低活跃频率单位-1不限制永不冻结',
`timeout` bigint(20) DEFAULT 2592000 COMMENT 'Token有效期单位-1永不过期',
`active_timeout` bigint(20) NOT NULL DEFAULT -1 COMMENT 'Token最低活跃频率单位-1不限制永不冻结',
`timeout` bigint(20) NOT NULL DEFAULT 2592000 COMMENT 'Token有效期单位-1永不过期',
`is_concurrent` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否允许同一账号多地同时登录true允许false新登录挤掉旧登录',
`replaced_range` varchar(20) DEFAULT NULL COMMENT '顶人下线的范围CURR_DEVICE_TYPE当前客户端类型ALL_DEVICE_TYPE所有客户端类型',
`max_login_count` int NOT NULL DEFAULT -1 COMMENT '同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)',
`overflow_logout_mode` varchar(20) DEFAULT NULL COMMENT '溢出人数的下线方式LOGOUT注销下线KICKOUT踢人下线REPLACED顶人下线',
`status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态1启用2禁用',
`create_user` bigint(20) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
@@ -399,11 +403,3 @@ CREATE TABLE IF NOT EXISTS `sys_sms_log` (
INDEX `idx_config_id`(`config_id`),
INDEX `idx_create_user`(`create_user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='短信日志表';
-- changeset KAI:20251125-01
-- comment 追加sys_client表字段
ALTER TABLE `sys_client`
ADD COLUMN `is_concurrent` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否允许同一账号多地同时登录',
ADD COLUMN `max_login_count` int NOT NULL DEFAULT -1 COMMENT '同一账号最大登录数量,-1代表不限',
ADD COLUMN `replaced_range` varchar(20) DEFAULT 'ALL_DEVICE_TYPE' COMMENT '顶人下线的范围CURR_DEVICE_TYPE=当前设备类型端ALL_DEVICE_TYPE=所有设备类型端)',
ADD COLUMN `overflow_logout_mode` varchar(20) DEFAULT 'KICKOUT' COMMENT '溢出人数的注销方式LOGOUT=注销下线KICKOUT=踢人下线REPLACED=顶人下线)';

View File

@@ -572,6 +572,10 @@ CREATE TABLE IF NOT EXISTS "sys_client" (
"auth_type" json NOT NULL,
"active_timeout" int8 NOT NULL DEFAULT -1,
"timeout" int8 NOT NULL DEFAULT 2592000,
"is_concurrent" bool NOT NULL DEFAULT true,
"replaced_range" varchar(20) DEFAULT NULL,
"max_login_count" int4 NOT NULL DEFAULT -1,
"overflow_logout_mode" varchar(20) DEFAULT NULL,
"status" int2 NOT NULL DEFAULT 1,
"create_user" int8 NOT NULL,
"create_time" timestamp NOT NULL,
@@ -590,6 +594,10 @@ COMMENT ON COLUMN "sys_client"."client_type" IS '客户端类型';
COMMENT ON COLUMN "sys_client"."auth_type" IS '认证类型';
COMMENT ON COLUMN "sys_client"."active_timeout" IS 'Token最低活跃频率单位-1不限制永不冻结';
COMMENT ON COLUMN "sys_client"."timeout" IS 'Token有效期单位-1永不过期';
COMMENT ON COLUMN "sys_client"."is_concurrent" IS '是否允许同一账号多地同时登录true允许false新登录挤掉旧登录';
COMMENT ON COLUMN "sys_client"."replaced_range" IS '顶人下线的范围CURR_DEVICE_TYPE当前客户端类型ALL_DEVICE_TYPE所有客户端类型';
COMMENT ON COLUMN "sys_client"."max_login_count" IS '同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)';
COMMENT ON COLUMN "sys_client"."overflow_logout_mode" IS '溢出人数的下线方式LOGOUT注销下线KICKOUT踢人下线REPLACED顶人下线';
COMMENT ON COLUMN "sys_client"."status" IS '状态1启用2禁用';
COMMENT ON COLUMN "sys_client"."create_user" IS '创建人';
COMMENT ON COLUMN "sys_client"."create_time" IS '创建时间';
@@ -666,16 +674,3 @@ COMMENT ON COLUMN "sys_sms_log"."res_msg" IS '返回数据';
COMMENT ON COLUMN "sys_sms_log"."create_user" IS '创建人';
COMMENT ON COLUMN "sys_sms_log"."create_time" IS '创建时间';
COMMENT ON TABLE "sys_sms_log" IS '短信日志表';
-- changeset kai:20251125-01
-- comment 追加sys_client表字段
ALTER TABLE "sys_client"
ADD COLUMN "is_concurrent" bool NOT NULL DEFAULT false,
ADD COLUMN "max_login_count" int4 NOT NULL DEFAULT -1,
ADD COLUMN "replaced_range" varchar(20) NOT NULL DEFAULT 'ALL_DEVICE_TYPE',
ADD COLUMN "overflow_logout_mode" varchar(20) NOT NULL DEFAULT 'KICKOUT';
COMMENT ON COLUMN "sys_client"."is_concurrent" IS '是否允许同一账号多地同时登录';
COMMENT ON COLUMN "sys_client"."max_login_count" IS '同一账号最大登录数量,-1代表不限';
COMMENT ON COLUMN "sys_client"."replaced_range" IS '顶人下线的范围CURR_DEVICE_TYPE=当前设备类型端ALL_DEVICE_TYPE=所有设备类型端)';
COMMENT ON COLUMN "sys_client"."overflow_logout_mode" IS '溢出人数的注销方式LOGOUT=注销下线KICKOUT=踢人下线REPLACED=顶人下线)';

View File

@@ -123,11 +123,15 @@ public abstract class AbstractLoginHandler<T extends LoginReq> implements LoginH
loginParameter.setTimeout(client.getTimeout());
loginParameter.setDeviceType(client.getClientType());
loginParameter.setExtra(CLIENT_ID, client.getClientId());
// 设置并发登录相关参数
// 设置并发登录配置参数
loginParameter.setIsConcurrent(client.getIsConcurrent());
loginParameter.setMaxLoginCount(client.getMaxLoginCount());
loginParameter.setOverflowLogoutMode(SaLogoutMode.valueOf(client.getOverflowLogoutMode().getValue()));
if (Boolean.FALSE.equals(client.getIsConcurrent())) {
loginParameter.setReplacedRange(SaReplacedRange.valueOf(client.getReplacedRange().getValue()));
}
loginParameter.setMaxLoginCount(client.getMaxLoginCount());
if (client.getMaxLoginCount() != -1) {
loginParameter.setOverflowLogoutMode(SaLogoutMode.valueOf(client.getOverflowLogoutMode().getValue()));
}
userContext.setClientType(client.getClientType());
userContext.setClientId(client.getClientId());
userContext.setTenantId(tenantId);

View File

@@ -24,7 +24,7 @@ import top.continew.starter.core.enums.BaseEnum;
* 注销模式枚举
*
* @author KAI
* @since 2025-10-28 14:04
* @since 2025/10/28 14:04
*/
@Getter
@RequiredArgsConstructor
@@ -47,5 +47,4 @@ public enum LogoutModeEnum implements BaseEnum<String> {
private final String value;
private final String description;
}

View File

@@ -24,23 +24,22 @@ import top.continew.starter.core.enums.BaseEnum;
* 顶人下线的范围枚举
*
* @author KAI
* @since 2025-10-28 14:05
* @since 2025/10/28 14:05
*/
@Getter
@RequiredArgsConstructor
public enum ReplacedRangeEnum implements BaseEnum<String> {
/**
* 当前指定的设备类型
* 当前客户端类型
*/
CURR_DEVICE_TYPE("CURR_DEVICE_TYPE", "当前指定的设备类型"),
CURR_DEVICE_TYPE("CURR_DEVICE_TYPE", "当前客户端类型"),
/**
* 所有设备类型
* 所有客户端类型
*/
ALL_DEVICE_TYPE("ALL_DEVICE_TYPE", "所有设备类型");
ALL_DEVICE_TYPE("ALL_DEVICE_TYPE", "所有客户端类型");
private final String value;
private final String description;
}

View File

@@ -69,22 +69,22 @@ public class ClientDO extends BaseDO {
private Long timeout;
/**
* 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false新登录挤掉旧登录)
* 是否允许同一账号多地同时登录true允许false新登录挤掉旧登录)
*/
private Boolean isConcurrent;
/**
* 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置项才有意义)
*/
private int maxLoginCount;
/**
* 当 isConcurrent=false 时,顶人下线的范围 (CURR_DEVICE_TYPE=当前指定的设备类型端, ALL_DEVICE_TYPE=所有设备类型端)
* 顶人下线的范围
*/
private ReplacedRangeEnum replacedRange;
/**
* 溢出 maxLoginCount 的客户端,将以何种方式注销下线 (LOGOUT=注销下线, KICKOUT=踢人下线, REPLACED=顶人下线)
* 同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)
*/
private Integer maxLoginCount;
/**
* 溢出人数的下线方式
*/
private LogoutModeEnum overflowLogoutMode;

View File

@@ -16,6 +16,8 @@
package top.continew.admin.system.model.req;
import cn.sticki.spel.validator.constrain.SpelNotNull;
import cn.sticki.spel.validator.jakarta.SpelValid;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
@@ -38,6 +40,7 @@ import java.util.List;
* @since 2024/12/03 16:04
*/
@Data
@SpelValid
@Schema(description = "客户端创建或修改请求参数")
public class ClientReq implements Serializable {
@@ -74,31 +77,31 @@ public class ClientReq implements Serializable {
private Long timeout;
/**
* 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false新登录挤掉旧登录)
* 是否允许同一账号多地同时登录true允许false新登录挤掉旧登录)
*/
@Schema(description = "是否允许同一账号多地同时登录", example = "true")
@NotNull(message = "是否运行同一账号多地同时登录不能为空")
@NotNull(message = "是否允许同一账号多地同时登录不能为空")
private Boolean isConcurrent;
/**
* 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置项才有意义)
*/
@Schema(description = "同一账号最大登录数量, -1代表不限", example = "-1")
@NotNull(message = "同一账号最大登录数量不能为空")
private int maxLoginCount;
/**
* 当 isConcurrent=false 时,顶人下线的范围 (CURR_DEVICE_TYPE=当前指定的设备类型端, ALL_DEVICE_TYPE=所有设备类型端)
* 顶人下线的范围
*/
@Schema(description = "顶人下线的范围", example = "ALL_DEVICE_TYPE")
@NotNull(message = "顶人下线的范围不能为空")
@SpelNotNull(condition = "#this.isConcurrent == false", message = "顶人下线的范围无效")
private ReplacedRangeEnum replacedRange;
/**
* 溢出 maxLoginCount 的客户端,将以何种方式注销下线 (LOGOUT=注销下线, KICKOUT=踢人下线, REPLACED=顶人下线)
* 同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)
*/
@Schema(description = "溢出人数的注销方式", example = "KICKOUT")
@NotNull(message = "溢出人数的注销方式不能为空")
@Schema(description = "同一账号最大登录数量", example = "-1")
@NotNull(message = "同一账号最大登录数量不能为空")
private Integer maxLoginCount;
/**
* 溢出人数的下线方式
*/
@Schema(description = "溢出人数的下线方式", example = "KICKOUT")
@SpelNotNull(condition = "#this.maxLoginCount != -1", message = "溢出人数的下线方式无效")
private LogoutModeEnum overflowLogoutMode;
/**

View File

@@ -84,37 +84,37 @@ public class ClientResp extends BaseDetailResp {
private Long timeout;
/**
* 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false新登录挤掉旧登录)
* 是否允许同一账号多地同时登录true允许false新登录挤掉旧登录)
*/
@Schema(description = "是否允许同一账号多地同时登录", example = "true")
@ExcelProperty(value = "是否允许同一账号多地同时登录", order = 8)
private Boolean isConcurrent;
/**
* 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置项才有意义)
* 顶人下线的范围
*/
@Schema(description = "同一账号最大登录数量, -1代表不限", example = "-1")
@ExcelProperty(value = "同一账号最大登录数量", order = 10)
private int maxLoginCount;
/**
* 当 isConcurrent=false 时,顶人下线的范围 (CURR_DEVICE_TYPE=当前指定的设备类型端, ALL_DEVICE_TYPE=所有设备类型端)
*/
@Schema(description = "顶人下线的范围 (CURR_DEVICE_TYPE=当前指定的设备类型端, ALL_DEVICE_TYPE=所有设备类型端)", example = "ALL_DEVICE_TYPE")
@ExcelProperty(value = "顶人下线的范围", converter = ExcelBaseEnumConverter.class, order = 11)
@Schema(description = "顶人下线的范围", example = "ALL_DEVICE_TYPE")
@ExcelProperty(value = "顶人下线的范围", converter = ExcelBaseEnumConverter.class, order = 9)
private ReplacedRangeEnum replacedRange;
/**
* 溢出 maxLoginCount 的客户端,将以何种方式注销下线 (LOGOUT=注销下线, KICKOUT=踢人下线, REPLACED=顶人下线)
* 同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)
*/
@Schema(description = "溢出人数的注销方式", example = "KICKOUT")
@ExcelProperty(value = "溢出人数的注销方式", converter = ExcelBaseEnumConverter.class, order = 12)
@Schema(description = "同一账号最大登录数量", example = "-1")
@ExcelProperty(value = "同一账号最大登录数量", order = 10)
private Integer maxLoginCount;
/**
* 溢出人数的下线方式
*/
@Schema(description = "溢出人数的下线方式", example = "KICKOUT")
@ExcelProperty(value = "溢出人数的下线方式", converter = ExcelBaseEnumConverter.class, order = 11)
private LogoutModeEnum overflowLogoutMode;
/**
* 状态
*/
@Schema(description = "状态", example = "1")
@ExcelProperty(value = "状态", converter = ExcelBaseEnumConverter.class, order = 13)
@ExcelProperty(value = "状态", converter = ExcelBaseEnumConverter.class, order = 12)
private DisEnableStatusEnum status;
}