优化代码语法,token采用jwt加强
This commit is contained in:
@@ -13,6 +13,17 @@
|
||||
<!-- 依赖 -->
|
||||
<dependencies>
|
||||
<!-- xtools begin -->
|
||||
<!-- xtools-extend begin -->
|
||||
<!-- JSON WEB令牌 -->
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xujun</groupId>
|
||||
<artifactId>xtools-extend</artifactId>
|
||||
</dependency>
|
||||
<!-- xtools-extend end -->
|
||||
<!-- xtools-web 模块 -->
|
||||
<dependency>
|
||||
<groupId>org.xujun</groupId>
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package xtools.app.sys.auth.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* <p>Title : AuthConfig</p>
|
||||
* <p>Description : AuthConfig</p>
|
||||
* <p>DevelopTools : Idea_x64_v2026.1</p>
|
||||
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : XuJun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026/2/16 11:01
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "auth")
|
||||
public class AuthConfig {
|
||||
|
||||
/**
|
||||
* 密钥
|
||||
*/
|
||||
private String secret = "xtools-app";
|
||||
}
|
||||
+8
-1
@@ -12,6 +12,7 @@ import org.springframework.stereotype.Component;
|
||||
import xtools.app.common.cache.enums.AppCache;
|
||||
import xtools.app.sys.auth.model.dto.LoginUserDto;
|
||||
import xtools.app.sys.auth.model.dto.OptLogDto;
|
||||
import xtools.app.sys.auth.utils.AuthJwtUtils;
|
||||
import xtools.app.sys.auth.utils.AuthUtils;
|
||||
import xtools.app.sys.auth.utils.PremUtils;
|
||||
import xtools.app.sys.auth.whitelist.AuthWhitelist;
|
||||
@@ -189,12 +190,18 @@ public class AuthFilter extends BaseFilter implements Ordered, BootCommonConstan
|
||||
}
|
||||
|
||||
// 校验登录权限
|
||||
String accessToken = AuthUtils.getAccessToken(request);
|
||||
String jwt = AuthUtils.getAccessToken(request);
|
||||
JSONObject jwtToken = AuthJwtUtils.verifyToken(jwt);
|
||||
String accessToken = jwtToken.getString(AuthUtils.JWT_TOKEN);
|
||||
LoginUserDto loginUser = AuthUtils.get(accessToken);
|
||||
if (Objects.isNull(loginUser)) {
|
||||
HttpServletUtils.respWriter(response, JSONObject.from(new Result<>(ResultType.UNAUTHORIZED, null)));
|
||||
return;
|
||||
}
|
||||
if (!AuthUtils.checkJwtToken(jwtToken, uid, loginUser.getId())) {
|
||||
HttpServletUtils.respWriter(response, JSONObject.from(new Result<>(ResultType.UNAUTHORIZED, null)));
|
||||
return;
|
||||
}
|
||||
log.setAccountId(loginUser.getId());
|
||||
log.setAccount(loginUser.getAccount());
|
||||
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package xtools.app.sys.auth.utils;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.interfaces.JWTVerifier;
|
||||
import xtools.app.sys.auth.config.AuthConfig;
|
||||
import xtools.boot.core.utils.SpringContextUtils;
|
||||
import xtools.extend.JwtUtils;
|
||||
|
||||
/**
|
||||
* <p>Title : AuthJwtUtils</p>
|
||||
* <p>Description : AuthJwtUtils</p>
|
||||
* <p>DevelopTools : Idea_x64_v2026.2.0.1</p>
|
||||
* <p>DevelopSystem : macOS Tahoe 26.6</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : XuJun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026/8/6 15:42
|
||||
*/
|
||||
public class AuthJwtUtils {
|
||||
|
||||
/**
|
||||
* 签名算法
|
||||
*/
|
||||
private static volatile Algorithm algorithm;
|
||||
|
||||
/**
|
||||
* 验证器
|
||||
*/
|
||||
private static volatile JWTVerifier verifier;
|
||||
|
||||
/**
|
||||
* 获取 Token
|
||||
*
|
||||
* @param data 数据
|
||||
* @param expireTime 过期时间
|
||||
* @return Token
|
||||
*/
|
||||
public static String getToken(JSONObject data, long expireTime) {
|
||||
if (algorithm == null) {
|
||||
AuthConfig config = SpringContextUtils.getBean(AuthConfig.class);
|
||||
synchronized (AuthJwtUtils.class) {
|
||||
if (algorithm == null) {
|
||||
algorithm = JwtUtils.getAlgorithm(config.getSecret());
|
||||
}
|
||||
}
|
||||
}
|
||||
return JwtUtils.getToken(algorithm, data, expireTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证 Token
|
||||
*
|
||||
* @param token Token
|
||||
* @return 数据
|
||||
*/
|
||||
public static JSONObject verifyToken(String token) {
|
||||
if (verifier == null) {
|
||||
AuthConfig config = SpringContextUtils.getBean(AuthConfig.class);
|
||||
synchronized (AuthJwtUtils.class) {
|
||||
if (verifier == null) {
|
||||
verifier = JwtUtils.getVerifier(config.getSecret());
|
||||
}
|
||||
}
|
||||
}
|
||||
return JwtUtils.verifyToken(verifier, token);
|
||||
}
|
||||
|
||||
}
|
||||
+66
-10
@@ -6,7 +6,6 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import xtools.app.common.cache.enums.AppCache;
|
||||
import xtools.app.sys.auth.model.dto.LoginUserDto;
|
||||
import xtools.app.sys.auth.model.dto.TokenDto;
|
||||
import static xtools.base.config.Constants.*;
|
||||
import xtools.boot.api.constant.BootCommonConstant;
|
||||
import xtools.boot.api.exection.BizError;
|
||||
import xtools.boot.api.exection.UnauthorizedError;
|
||||
@@ -25,6 +24,9 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static xtools.base.config.Constants.CP_COLON;
|
||||
import static xtools.base.config.Constants.CP_NUM16;
|
||||
|
||||
/**
|
||||
* <p>Title : AuthUtils</p>
|
||||
* <p>Description : AuthUtils</p>
|
||||
@@ -38,6 +40,11 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*/
|
||||
public class AuthUtils {
|
||||
|
||||
/**
|
||||
* jwtToken
|
||||
*/
|
||||
public static final String JWT_TOKEN = "token";
|
||||
|
||||
/**
|
||||
* 缓存参数
|
||||
*/
|
||||
@@ -63,6 +70,11 @@ public class AuthUtils {
|
||||
*/
|
||||
private static final String USER = "id";
|
||||
|
||||
/**
|
||||
* uid
|
||||
*/
|
||||
private static final String UID = "uid";
|
||||
|
||||
/**
|
||||
* mask
|
||||
*/
|
||||
@@ -112,13 +124,48 @@ public class AuthUtils {
|
||||
return HeaderUtils.getRequestParam(request, BootCommonConstant.UID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Jwt 中获取 token
|
||||
*
|
||||
* @param jwt Jwt信息
|
||||
* @param uid Uid
|
||||
* @param id Id
|
||||
* @return token
|
||||
*/
|
||||
public static String getTokenByJwt(String jwt, String uid, Long id) {
|
||||
JSONObject jwtToken = AuthJwtUtils.verifyToken(jwt);
|
||||
if (checkJwtToken(jwtToken, uid, id)) {
|
||||
return jwtToken.getString(JWT_TOKEN);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证 JwtToken
|
||||
*
|
||||
* @param jwtToken jwtToken
|
||||
* @param uid Uid
|
||||
* @param id Id
|
||||
* @return 是否通过验证
|
||||
*/
|
||||
public static boolean checkJwtToken(JSONObject jwtToken, String uid, Long id) {
|
||||
if (!Objects.equals(jwtToken.getString(UID), uid)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(jwtToken.getLong(USER), id)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 Token
|
||||
*
|
||||
* @param loginUser 登录用户信息
|
||||
* @param uid Uid
|
||||
* @return Token 信息
|
||||
*/
|
||||
public static TokenDto createToken(LoginUserDto loginUser) {
|
||||
public static TokenDto createToken(LoginUserDto loginUser, String uid) {
|
||||
Long userId = loginUser.getId();
|
||||
remove(userId);
|
||||
|
||||
@@ -131,18 +178,16 @@ public class AuthUtils {
|
||||
|
||||
RedisService redis = RedisUtils.get();
|
||||
// 保存 accessToken信息
|
||||
redis.set(getCacheKey(ACCESS_TOKEN, accessToken),
|
||||
JSONObject.of("expiryTime", userExpiryTime, "loginUser", loginUser), refreshTokenExpiryTime);
|
||||
redis.set(getCacheKey(ACCESS_TOKEN, accessToken), JSONObject.of("expiryTime", userExpiryTime, "loginUser", loginUser), refreshTokenExpiryTime);
|
||||
// 保存 refreshToken信息
|
||||
redis.set(getCacheKey(REFRESH_TOKEN, refreshToken), accessToken, refreshTokenExpiryTime);
|
||||
// 保存用户 Token 信息
|
||||
redis.set(getCacheKey(USER, userId),
|
||||
JSONObject.of(ACCESS_TOKEN, accessToken, REFRESH_TOKEN, refreshToken), refreshTokenExpiryTime);
|
||||
redis.set(getCacheKey(USER, userId), JSONObject.of(ACCESS_TOKEN, accessToken, REFRESH_TOKEN, refreshToken), refreshTokenExpiryTime);
|
||||
|
||||
// 构建 Token 信息
|
||||
TokenDto token = new TokenDto();
|
||||
token.setAccessToken(accessToken);
|
||||
token.setRefreshToken(refreshToken);
|
||||
token.setAccessToken(AuthJwtUtils.getToken(JSONObject.of(JWT_TOKEN, accessToken, UID, uid, USER, userId), accessTokenExpiryTime));
|
||||
token.setRefreshToken(AuthJwtUtils.getToken(JSONObject.of(JWT_TOKEN, refreshToken, UID, uid, USER, userId), refreshTokenExpiryTime));
|
||||
token.setExpiryTime(userExpiryTime);
|
||||
return token;
|
||||
}
|
||||
@@ -244,9 +289,15 @@ public class AuthUtils {
|
||||
* 刷新 Token
|
||||
*
|
||||
* @param refreshToken RefreshToken
|
||||
* @param uid Uid
|
||||
* @return Token
|
||||
*/
|
||||
public static TokenDto refreshToken(String refreshToken) {
|
||||
public static TokenDto refreshToken(String refreshToken, String uid) {
|
||||
if (StringUtils.isBlank(uid)) {
|
||||
throw new BizError("uid 不能为空");
|
||||
}
|
||||
JSONObject jwtToken = AuthJwtUtils.verifyToken(refreshToken);
|
||||
refreshToken = jwtToken.getString(AuthUtils.JWT_TOKEN);
|
||||
if (StringUtils.isBlank(refreshToken)) {
|
||||
throw new BizError("refreshToken 不能为空");
|
||||
}
|
||||
@@ -259,9 +310,14 @@ public class AuthUtils {
|
||||
if (loginUser == null) {
|
||||
throw new BizError("token已过期,请重新登录");
|
||||
}
|
||||
return createToken(loginUser);
|
||||
if (!checkJwtToken(jwtToken, uid, loginUser.getId())) {
|
||||
remove(loginUser.getId());
|
||||
throw new BizError("token异常,请重新登录");
|
||||
}
|
||||
return createToken(loginUser, uid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取是否忽略脱敏
|
||||
*
|
||||
|
||||
+8
-1
@@ -5,7 +5,6 @@ import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import xtools.app.common.cache.enums.AppCache;
|
||||
import xtools.app.sys.auth.model.dto.InterfacePermDto;
|
||||
import static xtools.base.config.Constants.*;
|
||||
import xtools.boot.cache.redis.base.RedisService;
|
||||
import xtools.boot.cache.redis.utils.RedisUtils;
|
||||
import xtools.core.CollectionUtils;
|
||||
@@ -15,6 +14,14 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static xtools.base.config.Constants.CP_COLON;
|
||||
import static xtools.base.config.Constants.CP_EMPTY;
|
||||
import static xtools.base.config.Constants.CP_LINE;
|
||||
import static xtools.base.config.Constants.CP_NUM1;
|
||||
import static xtools.base.config.Constants.CP_NUM2;
|
||||
import static xtools.base.config.Constants.CP_NUM7;
|
||||
import static xtools.base.config.Constants.CP_SLASH;
|
||||
|
||||
/**
|
||||
* <p>Title : PremUtils</p>
|
||||
* <p>Description : PremUtils</p>
|
||||
|
||||
+3
-2
@@ -62,9 +62,10 @@ public class SysLoginController {
|
||||
public Result<TokenDto> refresh(
|
||||
@Schema(description = "刷新令牌", example = "refreshToken")
|
||||
@NotNull(message = "不能为空")
|
||||
@PathVariable String refreshToken
|
||||
@PathVariable String refreshToken,
|
||||
HttpServletRequest request
|
||||
) {
|
||||
return Result.ok(AuthUtils.refreshToken(refreshToken));
|
||||
return Result.ok(AuthUtils.refreshToken(refreshToken, AuthUtils.getUid(request)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -5,7 +5,8 @@ import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Component;
|
||||
import xtools.app.sys.mapper.SysDictMapper;
|
||||
import xtools.app.sys.model.entity.SysDict;
|
||||
import static xtools.base.config.Constants.*;
|
||||
|
||||
import static xtools.base.config.Constants.CP_NUM1;
|
||||
|
||||
/**
|
||||
* <p>Title : SysDictBaseService</p>
|
||||
|
||||
-1
@@ -14,7 +14,6 @@ import xtools.app.sys.model.dto.resp.SysAddressResp;
|
||||
import xtools.app.sys.model.entity.SysAddress;
|
||||
import xtools.app.sys.service.SysAddressService;
|
||||
import xtools.app.sys.service.base.SysAddressBaseService;
|
||||
import static xtools.base.config.Constants.*;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
import xtools.boot.cache.redis.base.RedisService;
|
||||
import xtools.core.StringUtils;
|
||||
|
||||
+4
-1
@@ -26,7 +26,6 @@ import xtools.app.sys.service.SysUserPasswdRuleService;
|
||||
import xtools.app.sys.service.SysUserService;
|
||||
import xtools.app.sys.service.base.SysUserBaseService;
|
||||
import xtools.app.sys.utils.PasswdUtils;
|
||||
import static xtools.base.config.Constants.*;
|
||||
import xtools.boot.api.exection.BizError;
|
||||
import xtools.boot.api.exection.BizWarning;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
@@ -42,6 +41,10 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static xtools.base.config.Constants.CP_NUM0;
|
||||
import static xtools.base.config.Constants.CP_NUM1;
|
||||
import static xtools.base.config.Constants.CP_NUM20;
|
||||
|
||||
/**
|
||||
* <p>Title : SysBaseServiceImpl</p>
|
||||
* <p>Description : SysBaseServiceImpl</p>
|
||||
|
||||
+4
-1
@@ -15,7 +15,6 @@ import xtools.app.sys.model.dto.resp.SysDeptTreeResp;
|
||||
import xtools.app.sys.model.entity.SysDept;
|
||||
import xtools.app.sys.service.SysDeptService;
|
||||
import xtools.app.sys.service.base.SysDeptBaseService;
|
||||
import static xtools.base.config.Constants.*;
|
||||
import xtools.boot.api.exection.BizError;
|
||||
import xtools.boot.api.exection.BizWarning;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
@@ -38,6 +37,10 @@ import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static xtools.base.config.Constants.CP_COMMA;
|
||||
import static xtools.base.config.Constants.CP_EMPTY_JSON;
|
||||
import static xtools.base.config.Constants.CP_NUM1;
|
||||
|
||||
/**
|
||||
* <p>Title : SysDeptServiceImpl</p>
|
||||
* <p>Description : 部门管理表 ServiceImpl</p>
|
||||
|
||||
-1
@@ -16,7 +16,6 @@ import xtools.app.sys.model.entity.SysDict;
|
||||
import xtools.app.sys.service.SysDictItemService;
|
||||
import xtools.app.sys.service.SysDictService;
|
||||
import xtools.app.sys.service.base.SysDictBaseService;
|
||||
import static xtools.base.config.Constants.*;
|
||||
import xtools.boot.api.enums.StatusEnum;
|
||||
import xtools.boot.api.exection.BizError;
|
||||
import xtools.boot.api.exection.BizWarning;
|
||||
|
||||
+2
-2
@@ -145,7 +145,7 @@ public class SysLoginServiceImpl implements SysLoginService {
|
||||
redisService.set(cacheParam.key(uid), arithmeticDto.getResult(), cacheParam.expireTime());
|
||||
|
||||
// 转换为base64的验证码
|
||||
return "data:image/png;base64," + new String(Base64Utils.encode(imgCode));
|
||||
return "data:image/png;base64," + new String(Base64Utils.encode(imgCode) == null ? new byte[0] : imgCode);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,7 +208,7 @@ public class SysLoginServiceImpl implements SysLoginService {
|
||||
LoginUserDto loginUserDto = sysLoginConvert.entityToCacheDto(user);
|
||||
loginUserDto.setRoleIds(sysUserRoleBaseService.getUserRole(user.getId()));
|
||||
redisService.del(captchaKey);
|
||||
return Result.ok(AuthUtils.createToken(loginUserDto));
|
||||
return Result.ok(AuthUtils.createToken(loginUserDto, uid));
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-1
@@ -23,7 +23,6 @@ import xtools.app.sys.service.SysUserNoticeService;
|
||||
import xtools.app.sys.service.base.SysNoticeBaseService;
|
||||
import xtools.app.sys.service.base.SysUserBaseService;
|
||||
import xtools.app.sys.service.base.SysUserNoticeBaseService;
|
||||
import static xtools.base.config.Constants.*;
|
||||
import xtools.boot.api.exection.BizError;
|
||||
import xtools.boot.api.exection.BizWarning;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
@@ -41,6 +40,9 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static xtools.base.config.Constants.CP_NUM1;
|
||||
import static xtools.base.config.Constants.CP_NUM2;
|
||||
|
||||
/**
|
||||
* <p>Title : SysNoticeServiceImpl</p>
|
||||
* <p>Description : 系统通知公告表 ServiceImpl</p>
|
||||
|
||||
+4
-1
@@ -6,7 +6,6 @@ import org.springframework.stereotype.Service;
|
||||
import xtools.app.sys.model.entity.SysUserPasswdRule;
|
||||
import xtools.app.sys.service.SysPasswdService;
|
||||
import xtools.app.sys.service.SysUserPasswdRuleService;
|
||||
import static xtools.base.config.Constants.*;
|
||||
import xtools.boot.api.exection.BizError;
|
||||
import xtools.boot.api.exection.BizWarning;
|
||||
import xtools.core.StringUtils;
|
||||
@@ -16,6 +15,10 @@ import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static xtools.base.config.Constants.CP_EMPTY;
|
||||
import static xtools.base.config.Constants.CP_NUM0;
|
||||
import static xtools.base.config.Constants.CP_NUM3;
|
||||
|
||||
/**
|
||||
* <p>Title : SysPasswdServiceImpl</p>
|
||||
* <p>Description : SysPasswdServiceImpl</p>
|
||||
|
||||
+2
-1
@@ -17,7 +17,6 @@ import xtools.app.sys.service.SysUserNoticeInfoService;
|
||||
import xtools.app.sys.service.base.SysNoticeBaseService;
|
||||
import xtools.app.sys.service.base.SysUserNoticeBaseService;
|
||||
import xtools.app.sys.service.base.SysUserNoticeInfoBaseService;
|
||||
import static xtools.base.config.Constants.*;
|
||||
import xtools.boot.api.enums.DeleteEnum;
|
||||
import xtools.boot.api.exection.BizError;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
@@ -31,6 +30,8 @@ import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static xtools.base.config.Constants.CP_NUM1;
|
||||
|
||||
/**
|
||||
* <p>Title : SysUserNoticeInfoServiceImpl</p>
|
||||
* <p>Description : 系统用户通知公告信息表 ServiceImpl</p>
|
||||
|
||||
+2
-1
@@ -23,7 +23,6 @@ import xtools.app.sys.service.base.SysDeptBaseService;
|
||||
import xtools.app.sys.service.base.SysUserBaseService;
|
||||
import xtools.app.sys.service.base.SysUserRoleBaseService;
|
||||
import xtools.app.sys.utils.PasswdUtils;
|
||||
import static xtools.base.config.Constants.*;
|
||||
import xtools.boot.api.exection.BizError;
|
||||
import xtools.boot.api.exection.BizWarning;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
@@ -46,6 +45,8 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static xtools.base.config.Constants.CP_NUM0;
|
||||
|
||||
/**
|
||||
* <p>Title : SysUserServiceImpl</p>
|
||||
* <p>Description : 系统用户表 ServiceImpl</p>
|
||||
|
||||
@@ -8,7 +8,6 @@ import xtools.app.sys.enums.SysRiskType;
|
||||
import xtools.app.sys.model.dto.resp.SysRiskResp;
|
||||
import xtools.app.sys.risk.utils.RiskCaffeineUtils;
|
||||
import xtools.app.sys.risk.utils.UriRiskUtils;
|
||||
import static xtools.base.config.Constants.*;
|
||||
import xtools.core.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
Reference in New Issue
Block a user