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

@@ -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;
}
}