update 优化 客户端管理 增加白名单路径和白名单IP功能 可限制客户端能访问的具体路径与可访问的具体IP地址

This commit is contained in:
疯狂的狮子Li
2026-04-16 14:14:25 +08:00
parent a5e8951bcd
commit 981743da00
17 changed files with 323 additions and 49 deletions

View File

@@ -1,12 +1,16 @@
package org.dromara.web.service;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.util.ObjectUtil;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.system.domain.SysClient;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.vo.SysClientVo;
import org.dromara.web.domain.vo.LoginVo;
import java.util.function.Consumer;
/**
* 授权策略
*
@@ -34,6 +38,37 @@ public interface IAuthStrategy {
return instance.login(body, client);
}
/**
* 按客户端配置构建统一登录参数。
*
* @param client 客户端配置
* @return Sa-Token 登录参数
*/
static SaLoginParameter buildLoginParameter(SysClientVo client) {
return buildLoginParameter(client, null);
}
/**
* 按客户端配置构建统一登录参数,并预留自定义扩展入口。
*
* @param client 客户端配置
* @param customizer 自定义扩展逻辑
* @return Sa-Token 登录参数
*/
static SaLoginParameter buildLoginParameter(SysClientVo client, Consumer<SaLoginParameter> customizer) {
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
model.setExtra(LoginHelper.CLIENT_ACCESS_PATH_KEY, client.getAccessPath());
model.setExtra(LoginHelper.CLIENT_IP_WHITELIST_KEY, client.getIpWhitelist());
if (ObjectUtil.isNotNull(customizer)) {
customizer.accept(model);
}
return model;
}
/**
* 登录
*

View File

@@ -61,13 +61,7 @@ public class EmailAuthStrategy implements IAuthStrategy {
LoginUser loginUser = loginService.buildLoginUser(user);
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
SaLoginParameter model = IAuthStrategy.buildLoginParameter(client);
// 生成token
LoginHelper.login(loginUser, model);

View File

@@ -73,13 +73,7 @@ public class PasswordAuthStrategy implements IAuthStrategy {
LoginUser loginUser = loginService.buildLoginUser(user);
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
SaLoginParameter model = IAuthStrategy.buildLoginParameter(client);
// 生成token
LoginHelper.login(loginUser, model);

View File

@@ -61,13 +61,7 @@ public class SmsAuthStrategy implements IAuthStrategy {
LoginUser loginUser = loginService.buildLoginUser(user);
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
SaLoginParameter model = IAuthStrategy.buildLoginParameter(client);
// 生成token
LoginHelper.login(loginUser, model);

View File

@@ -73,13 +73,7 @@ public class SocialAuthStrategy implements IAuthStrategy {
LoginUser loginUser = loginService.buildLoginUser(user);
loginUser.setClientKey(client.getClientKey());
loginUser.setDeviceType(client.getDeviceType());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
SaLoginParameter model = IAuthStrategy.buildLoginParameter(client);
// 生成token
LoginHelper.login(loginUser, model);

View File

@@ -82,13 +82,7 @@ public class XcxAuthStrategy implements IAuthStrategy {
loginUser.setDeviceType(client.getDeviceType());
loginUser.setOpenid(openid);
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType(client.getDeviceType());
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
// 例如: 后台用户30分钟过期 app用户1天过期
model.setTimeout(client.getTimeout());
model.setActiveTimeout(client.getActiveTimeout());
model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
SaLoginParameter model = IAuthStrategy.buildLoginParameter(client);
// 生成token
LoginHelper.login(loginUser, model);

View File

@@ -7,6 +7,7 @@ import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.regex.RegexUtils;
import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -52,7 +53,8 @@ public class NetUtils extends NetUtil {
public static boolean isInnerIPv6(String ip) {
try {
// 判断是否为IPv6地址
if (InetAddress.getByName(ip) instanceof Inet6Address inet6Address) {
InetAddress inetAddress = InetAddress.getByName(ip);
if (inetAddress instanceof Inet6Address inet6Address) {
// isAnyLocalAddress 判断是否为通配符地址,通常不会将其视为内网地址,根据业务场景自行处理判断
// isLinkLocalAddress 判断是否为链路本地地址,通常不算内网地址,是否划分归属于内网需要根据业务场景自行处理判断
// isLoopbackAddress 判断是否为环回地址与IPv4的 127.0.0.1 同理,用于表示本机
@@ -81,4 +83,69 @@ public class NetUtils extends NetUtil {
return RegexUtils.isMatch(PatternPool.IPV4, ip);
}
/**
* 匹配 IP 规则,支持精确值、通配符与 CIDR。
*
* @param rule IP 规则
* @param clientIp 客户端 IP
* @return 是否匹配
*/
public static boolean isMatchIpRule(String rule, String clientIp) {
if (StringUtils.isBlank(rule) || StringUtils.isBlank(clientIp)) {
return false;
}
String ipRule = StringUtils.trim(rule);
if (StringUtils.equals(ipRule, clientIp)) {
return true;
}
if (ipRule.contains("/")) {
return isMatchCidr(ipRule, clientIp);
}
if (StringUtils.containsAny(ipRule, "*", "?")) {
String regex = ipRule
.replace(".", "\\.")
.replace("*", ".*")
.replace("?", ".");
return clientIp.matches(regex);
}
return false;
}
/**
* 匹配 CIDR 网段。
*
* @param cidr CIDR 规则
* @param clientIp 客户端 IP
* @return 是否命中
*/
public static boolean isMatchCidr(String cidr, String clientIp) {
try {
String[] parts = cidr.split("/");
if (parts.length != 2) {
return false;
}
InetAddress networkAddress = InetAddress.getByName(parts[0]);
InetAddress currentAddress = InetAddress.getByName(clientIp);
byte[] networkBytes = networkAddress.getAddress();
byte[] currentBytes = currentAddress.getAddress();
if (networkBytes.length != currentBytes.length) {
return false;
}
int prefixLength = Integer.parseInt(parts[1]);
int maxPrefix = networkBytes.length * 8;
if (prefixLength < 0 || prefixLength > maxPrefix) {
return false;
}
BigInteger mask = prefixLength == 0
? BigInteger.ZERO
: BigInteger.ONE.shiftLeft(prefixLength).subtract(BigInteger.ONE).shiftLeft(maxPrefix - prefixLength);
BigInteger network = new BigInteger(1, networkBytes);
BigInteger current = new BigInteger(1, currentBytes);
return network.and(mask).equals(current.and(mask));
} catch (UnknownHostException | NumberFormatException e) {
log.debug("IP白名单CIDR规则解析失败: {}", cidr, e);
return false;
}
}
}

View File

@@ -40,6 +40,8 @@ public class LoginHelper {
public static final String DEPT_NAME_KEY = "deptName";
public static final String DEPT_CATEGORY_KEY = "deptCategory";
public static final String CLIENT_KEY = "clientid";
public static final String CLIENT_ACCESS_PATH_KEY = "clientAccessPath";
public static final String CLIENT_IP_WHITELIST_KEY = "clientIpWhitelist";
/**
* 登录系统 基于 设备类型

View File

@@ -1,6 +1,7 @@
package org.dromara.common.security.config;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil;
import cn.dev33.satoken.interceptor.SaInterceptor;
@@ -13,6 +14,7 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.utils.NetUtils;
import org.dromara.common.core.utils.ServletUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
@@ -26,6 +28,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/**
* 权限安全配置
*
@@ -38,6 +42,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@RequiredArgsConstructor
public class SecurityConfig implements WebMvcConfigurer {
private static final String CLIENT_RULE_SEPARATOR_REGEX = "[,;\\r\\n]+";
private final SecurityProperties securityProperties;
@Value("${message.path:/resource/message}")
private String messagePath;
@@ -74,6 +80,7 @@ public class SecurityConfig implements WebMvcConfigurer {
"-100", "客户端ID与Token不匹配",
StpUtil.getTokenValue());
}
validateClientAccessRules(request);
// 有效率影响 用于临时测试
// if (log.isDebugEnabled()) {
@@ -109,4 +116,41 @@ public class SecurityConfig implements WebMvcConfigurer {
});
}
/**
* 按客户端配置校验接口访问路径与来源 IP。
*
* @param request 当前请求
*/
private void validateClientAccessRules(HttpServletRequest request) {
String requestPath = StringUtils.blankToDefault(request.getServletPath(), request.getRequestURI());
String accessPath = getTokenExtra(LoginHelper.CLIENT_ACCESS_PATH_KEY);
if (StringUtils.isNotBlank(accessPath)) {
List<String> accessPathList = StringUtils.str2List(accessPath, CLIENT_RULE_SEPARATOR_REGEX, true, true);
if (!StringUtils.matches(requestPath, accessPathList)) {
throw new NotPermissionException("当前客户端未授权访问该接口路径");
}
}
String ipWhitelist = getTokenExtra(LoginHelper.CLIENT_IP_WHITELIST_KEY);
if (StringUtils.isNotBlank(ipWhitelist)) {
String clientIp = ServletUtils.getClientIP(request);
List<String> ipWhitelistList = StringUtils.str2List(ipWhitelist, CLIENT_RULE_SEPARATOR_REGEX, true, true);
boolean matched = ipWhitelistList.stream().anyMatch(rule -> NetUtils.isMatchIpRule(rule, clientIp));
if (!matched) {
throw new NotPermissionException("当前客户端IP不在白名单内");
}
}
}
/**
* 读取 token 扩展信息,兼容空值场景。
*
* @param key 扩展字段
* @return 扩展值
*/
private String getTokenExtra(String key) {
Object extra = StpUtil.getExtra(key);
return extra == null ? null : extra.toString();
}
}

View File

@@ -54,6 +54,16 @@ public class SysClient extends BaseEntity {
*/
private String deviceType;
/**
* 允许访问路径
*/
private String accessPath;
/**
* IP白名单
*/
private String ipWhitelist;
/**
* token活跃超时时间
*/

View File

@@ -64,6 +64,26 @@ public class SysClientBo implements Serializable {
*/
private String deviceType;
/**
* 允许访问路径
*/
private String accessPath;
/**
* 允许访问路径列表
*/
private List<String> accessPathList;
/**
* IP白名单
*/
private String ipWhitelist;
/**
* IP白名单列表
*/
private List<String> ipWhitelistList;
/**
* token活跃超时时间
*/

View File

@@ -67,6 +67,28 @@ public class SysClientVo implements Serializable {
*/
private String deviceType;
/**
* 允许访问路径
*/
@ExcelProperty(value = "允许访问路径")
private String accessPath;
/**
* 允许访问路径列表
*/
private List<String> accessPathList;
/**
* IP白名单
*/
@ExcelProperty(value = "IP白名单")
private String ipWhitelist;
/**
* IP白名单列表
*/
private List<String> ipWhitelistList;
/**
* token活跃超时时间
*/

View File

@@ -25,6 +25,7 @@ import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.function.UnaryOperator;
/**
* 客户端管理Service业务层处理
@@ -37,6 +38,8 @@ import java.util.List;
@Service
public class SysClientServiceImpl implements ISysClientService {
private static final String CLIENT_RULE_SEPARATOR_REGEX = "[,;\\r\\n]+";
private final SysClientMapper baseMapper;
/**
@@ -48,7 +51,7 @@ public class SysClientServiceImpl implements ISysClientService {
@Override
public SysClientVo queryById(Long id) {
SysClientVo vo = baseMapper.selectVoById(id);
vo.setGrantTypeList(StringUtils.splitList(vo.getGrantType()));
fillClientRuleFields(vo);
return vo;
}
@@ -61,7 +64,9 @@ public class SysClientServiceImpl implements ISysClientService {
@Cacheable(cacheNames = CacheNames.SYS_CLIENT, key = "#clientId")
@Override
public SysClientVo queryByClientId(String clientId) {
return baseMapper.selectVoOne(new LambdaQueryWrapper<SysClient>().eq(SysClient::getClientId, clientId));
SysClientVo vo = baseMapper.selectVoOne(new LambdaQueryWrapper<SysClient>().eq(SysClient::getClientId, clientId));
fillClientRuleFields(vo);
return vo;
}
/**
@@ -75,7 +80,7 @@ public class SysClientServiceImpl implements ISysClientService {
public PageResult<SysClientVo> queryPageList(SysClientBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<SysClient> lqw = buildQueryWrapper(bo);
Page<SysClientVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
result.getRecords().forEach(r -> r.setGrantTypeList(StringUtils.splitList(r.getGrantType())));
result.getRecords().forEach(this::fillClientRuleFields);
return PageResult.build(result.getRecords(), result.getTotal());
}
@@ -88,7 +93,9 @@ public class SysClientServiceImpl implements ISysClientService {
@Override
public List<SysClientVo> queryList(SysClientBo bo) {
LambdaQueryWrapper<SysClient> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
List<SysClientVo> list = baseMapper.selectVoList(lqw);
list.forEach(this::fillClientRuleFields);
return list;
}
/**
@@ -117,6 +124,8 @@ public class SysClientServiceImpl implements ISysClientService {
public Boolean insertByBo(SysClientBo bo) {
SysClient add = MapstructUtils.convert(bo, SysClient.class);
add.setGrantType(CollUtil.join(bo.getGrantTypeList(), StringUtils.SEPARATOR));
add.setAccessPath(resolveRuleValue(bo.getAccessPath(), bo.getAccessPathList(), this::normalizeAccessPath));
add.setIpWhitelist(resolveRuleValue(bo.getIpWhitelist(), bo.getIpWhitelistList(), UnaryOperator.identity()));
// 生成clientid
String clientKey = bo.getClientKey();
String clientSecret = bo.getClientSecret();
@@ -139,6 +148,8 @@ public class SysClientServiceImpl implements ISysClientService {
public Boolean updateByBo(SysClientBo bo) {
SysClient update = MapstructUtils.convert(bo, SysClient.class);
update.setGrantType(StringUtils.joinComma(bo.getGrantTypeList()));
update.setAccessPath(resolveRuleValue(bo.getAccessPath(), bo.getAccessPathList(), this::normalizeAccessPath));
update.setIpWhitelist(resolveRuleValue(bo.getIpWhitelist(), bo.getIpWhitelistList(), UnaryOperator.identity()));
return baseMapper.updateById(update) > 0;
}
@@ -185,4 +196,73 @@ public class SysClientServiceImpl implements ISysClientService {
return !exist;
}
/**
* 回填客户端扩展规则字段,便于前端直接展示和编辑。
*
* @param vo 客户端视图对象
*/
private void fillClientRuleFields(SysClientVo vo) {
if (ObjectUtil.isNull(vo)) {
return;
}
vo.setGrantTypeList(StringUtils.splitList(vo.getGrantType()));
vo.setAccessPathList(parseRuleList(vo.getAccessPath(), this::normalizeAccessPath));
vo.setIpWhitelistList(parseRuleList(vo.getIpWhitelist(), UnaryOperator.identity()));
}
/**
* 统一处理白名单与路径规则的入库格式。
*
* @param rawValue 原始字符串
* @param listValue 列表值
* @param normalizer 单条规则归一化器
* @return 逗号拼接后的规则串
*/
private String resolveRuleValue(String rawValue, List<String> listValue, UnaryOperator<String> normalizer) {
List<String> rules = CollUtil.isNotEmpty(listValue)
? listValue
: StringUtils.str2List(rawValue, CLIENT_RULE_SEPARATOR_REGEX, true, true);
if (CollUtil.isEmpty(rules)) {
return listValue != null || rawValue != null ? "" : null;
}
return CollUtil.join(rules.stream()
.map(normalizer)
.filter(StringUtils::isNotBlank)
.toList(), StringUtils.SEPARATOR);
}
/**
* 将规则串转换为列表。
*
* @param value 规则串
* @param normalizer 单条规则归一化器
* @return 规则列表
*/
private List<String> parseRuleList(String value, UnaryOperator<String> normalizer) {
return StringUtils.str2List(value, CLIENT_RULE_SEPARATOR_REGEX, true, true).stream()
.map(normalizer)
.filter(StringUtils::isNotBlank)
.toList();
}
/**
* 统一补齐路径前导斜杠,避免配置成 app/** 时无法命中。
*
* @param path 路径规则
* @return 规范化后的路径规则
*/
private String normalizeAccessPath(String path) {
if (StringUtils.isBlank(path)) {
return null;
}
String accessPath = StringUtils.trim(path);
if (StringUtils.isBlank(accessPath)) {
return null;
}
if (StringUtils.equals(accessPath, "*") || StringUtils.equals(accessPath, "/**")) {
return "/**";
}
return accessPath.startsWith(StringUtils.SLASH) ? accessPath : StringUtils.SLASH + accessPath;
}
}

View File

@@ -1211,6 +1211,8 @@ create table sys_client (
client_secret varchar2(255) default null,
grant_type varchar2(255) default null,
device_type varchar2(32) default null,
access_path varchar2(2000) default null,
ip_whitelist varchar2(1000) default null,
active_timeout number(11) default 1800,
timeout number(11) default 604800,
status char(1) default '0',
@@ -1231,6 +1233,8 @@ comment on column sys_client.client_key is '客户端key';
comment on column sys_client.client_secret is '客户端秘钥';
comment on column sys_client.grant_type is '授权类型';
comment on column sys_client.device_type is '设备类型';
comment on column sys_client.access_path is '允许访问路径';
comment on column sys_client.ip_whitelist is 'IP白名单';
comment on column sys_client.active_timeout is 'token活跃超时时间';
comment on column sys_client.timeout is 'token固定超时';
comment on column sys_client.status is '状态0正常 1停用';
@@ -1241,8 +1245,8 @@ comment on column sys_client.create_time is '创建时间';
comment on column sys_client.update_by is '更新者';
comment on column sys_client.update_time is '更新时间';
insert into sys_client values (1762000000000000001, 'e5cd7e4891bf95d1d19206ce24a7b32e', 'pc', 'pc123', 'password,social', 'pc', 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, sysdate, 1761100000000000001, sysdate);
insert into sys_client values (1762000000000000002, '428a8310cd442757ae699df5d894f051', 'app', 'app123', 'password,sms,social', 'android', 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, sysdate, 1761100000000000001, sysdate);
insert into sys_client values (1762000000000000001, 'e5cd7e4891bf95d1d19206ce24a7b32e', 'pc', 'pc123', 'password,social', 'pc', null, null, 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, sysdate, 1761100000000000001, sysdate);
insert into sys_client values (1762000000000000002, '428a8310cd442757ae699df5d894f051', 'app', 'app123', 'password,sms,social', 'android', '/app/**', null, 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, sysdate, 1761100000000000001, sysdate);
create table test_demo (
id number(20) not null,

View File

@@ -1206,6 +1206,8 @@ create table sys_client (
client_secret varchar(255) default ''::varchar,
grant_type varchar(255) default ''::varchar,
device_type varchar(32) default ''::varchar,
access_path varchar(2000) default ''::varchar,
ip_whitelist varchar(1000) default ''::varchar,
active_timeout int4 default 1800,
timeout int4 default 604800,
status char(1) default '0'::bpchar,
@@ -1225,6 +1227,8 @@ comment on column sys_client.client_key is '客户端key';
comment on column sys_client.client_secret is '客户端秘钥';
comment on column sys_client.grant_type is '授权类型';
comment on column sys_client.device_type is '设备类型';
comment on column sys_client.access_path is '允许访问路径';
comment on column sys_client.ip_whitelist is 'IP白名单';
comment on column sys_client.active_timeout is 'token活跃超时时间';
comment on column sys_client.timeout is 'token固定超时';
comment on column sys_client.status is '状态0正常 1停用';
@@ -1235,8 +1239,8 @@ comment on column sys_client.create_time is '创建时间';
comment on column sys_client.update_by is '更新者';
comment on column sys_client.update_time is '更新时间';
insert into sys_client values (1762000000000000001, 'e5cd7e4891bf95d1d19206ce24a7b32e', 'pc', 'pc123', 'password,social', 'pc', 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, now(), 1761100000000000001, now());
insert into sys_client values (1762000000000000002, '428a8310cd442757ae699df5d894f051', 'app', 'app123', 'password,sms,social', 'android', 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, now(), 1761100000000000001, now());
insert into sys_client values (1762000000000000001, 'e5cd7e4891bf95d1d19206ce24a7b32e', 'pc', 'pc123', 'password,social', 'pc', '', '', 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, now(), 1761100000000000001, now());
insert into sys_client values (1762000000000000002, '428a8310cd442757ae699df5d894f051', 'app', 'app123', 'password,sms,social', 'android', '/app/**', '', 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, now(), 1761100000000000001, now());
create table if not exists test_demo
(

View File

@@ -852,6 +852,8 @@ create table sys_client (
client_secret varchar(255) default null comment '客户端秘钥',
grant_type varchar(255) default null comment '授权类型',
device_type varchar(32) default null comment '设备类型',
access_path varchar(2000) default null comment '允许访问路径',
ip_whitelist varchar(1000) default null comment 'IP白名单',
active_timeout int(11) default 1800 comment 'token活跃超时时间',
timeout int(11) default 604800 comment 'token固定超时',
status char(1) default '0' comment '状态0正常 1停用',
@@ -864,8 +866,8 @@ create table sys_client (
primary key (id)
) engine=innodb comment='系统授权表';
insert into sys_client values (1762000000000000001, 'e5cd7e4891bf95d1d19206ce24a7b32e', 'pc', 'pc123', 'password,social', 'pc', 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, sysdate(), 1761100000000000001, sysdate());
insert into sys_client values (1762000000000000002, '428a8310cd442757ae699df5d894f051', 'app', 'app123', 'password,sms,social', 'android', 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, sysdate(), 1761100000000000001, sysdate());
insert into sys_client values (1762000000000000001, 'e5cd7e4891bf95d1d19206ce24a7b32e', 'pc', 'pc123', 'password,social', 'pc', null, null, 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, sysdate(), 1761100000000000001, sysdate());
insert into sys_client values (1762000000000000002, '428a8310cd442757ae699df5d894f051', 'app', 'app123', 'password,sms,social', 'android', '/app/**', null, 1800, 604800, 0, 0, 1761000000000000103, 1761100000000000001, sysdate(), 1761100000000000001, sysdate());
CREATE TABLE test_demo

View File

@@ -3060,6 +3060,8 @@ CREATE TABLE sys_client
client_secret nvarchar(255) DEFAULT '' NULL,
grant_type nvarchar(255) DEFAULT '' NULL,
device_type nvarchar(32) DEFAULT '' NULL,
access_path nvarchar(2000) DEFAULT '' NULL,
ip_whitelist nvarchar(1000) DEFAULT '' NULL,
active_timeout int DEFAULT ((1800)) NULL,
timeout int DEFAULT ((604800)) NULL,
status nchar(1) DEFAULT ('0') NULL,
@@ -3112,6 +3114,18 @@ EXEC sp_addextendedproperty
'TABLE', N'sys_client',
'COLUMN', N'device_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'允许访问路径',
'SCHEMA', N'dbo',
'TABLE', N'sys_client',
'COLUMN', N'access_path'
GO
EXEC sp_addextendedproperty
'MS_Description', N'IP白名单',
'SCHEMA', N'dbo',
'TABLE', N'sys_client',
'COLUMN', N'ip_whitelist'
GO
EXEC sp_addextendedproperty
'MS_Description', N'token活跃超时时间',
'SCHEMA', N'dbo',
@@ -3172,9 +3186,9 @@ EXEC sp_addextendedproperty
'TABLE', N'sys_client'
GO
INSERT INTO sys_client VALUES (1762000000000000001, N'e5cd7e4891bf95d1d19206ce24a7b32e', N'pc', N'pc123', N'password,social', N'pc', 1800, 604800, N'0', N'0', 1761000000000000103, 1761100000000000001, getdate(), 1761100000000000001, getdate());
INSERT INTO sys_client VALUES (1762000000000000001, N'e5cd7e4891bf95d1d19206ce24a7b32e', N'pc', N'pc123', N'password,social', N'pc', N'', N'', 1800, 604800, N'0', N'0', 1761000000000000103, 1761100000000000001, getdate(), 1761100000000000001, getdate());
GO
INSERT INTO sys_client VALUES (1762000000000000002, N'428a8310cd442757ae699df5d894f051', N'app', N'app123', N'password,sms,social', N'android', 1800, 604800, N'0', N'0', 1761000000000000103, 1761100000000000001, getdate(), 1761100000000000001, getdate());
INSERT INTO sys_client VALUES (1762000000000000002, N'428a8310cd442757ae699df5d894f051', N'app', N'app123', N'password,sms,social', N'android', N'/app/**', N'', 1800, 604800, N'0', N'0', 1761000000000000103, 1761100000000000001, getdate(), 1761100000000000001, getdate());
GO
CREATE TABLE test_demo