This commit is contained in:
Luke.Ye 2026-03-24 11:52:02 +08:00
parent 147654f2e5
commit 958f5253df

View File

@ -36,24 +36,41 @@ public class UserQueryController {
@GetMapping("/check") @GetMapping("/check")
public ResponseEntity<?> check( public ResponseEntity<?> check(
@RequestHeader(value = "X-Auth-Token", required = false) String forwardedToken,
@CookieValue(value = ConstantConfig.COOKIE_KEY, required = false) String cookieToken, @CookieValue(value = ConstantConfig.COOKIE_KEY, required = false) String cookieToken,
@RequestHeader(value = "Authorization", required = false) String headerToken, @RequestHeader(value = "Authorization", required = false) String headerToken,
@RequestHeader(value = "Cookie", required = false) String rawCookie,
@RequestHeader(value = "X-Original-URI", required = false) String originalUri, @RequestHeader(value = "X-Original-URI", required = false) String originalUri,
@RequestHeader(value = "X-Original-HOST", required = false, defaultValue = StrUtil.EMPTY) String host @RequestHeader(value = "X-Original-HOST", required = false, defaultValue = StrUtil.EMPTY) String host
) { ) {
String token = headerToken != null ? headerToken : cookieToken; originalUri = URLDecoder.decode(
originalUri = URLDecoder.decode(originalUri, StandardCharsets.UTF_8); originalUri == null ? StrUtil.EMPTY : originalUri,
StandardCharsets.UTF_8
);
LOGGER.info("[权限校验] token={}, host={}, originalUri={}", headerToken != null ? headerToken : cookieToken, host, originalUri); String token = firstNonBlank(
forwardedToken,
normalizeAuthorization(headerToken),
cookieToken,
extractCookie(rawCookie, ConstantConfig.COOKIE_KEY)
);
if (token == null || token.isBlank()) { LOGGER.info("[权限校验] token={}, host={}, originalUri={}, rawCookieExists={}",
maskToken(token), host, originalUri, StrUtil.isNotBlank(rawCookie));
if (StrUtil.isBlank(token)) {
LOGGER.warn("[权限校验] 未提供token拒绝访问"); LOGGER.warn("[权限校验] 未提供token拒绝访问");
return ResponseEntity.status(401).body(Map.of("code", 401, "msg", "未授权")); return ResponseEntity.status(401).body(Map.of("code", 401, "msg", "未授权"));
} }
Optional<UserTokenDTO> userTokenOpt = userAppService.findToken(token); Optional<UserTokenDTO> userTokenOpt = null;
try {
userTokenOpt = userAppService.findToken(token);
} catch (Exception e) {
LOGGER.error("userAppService.findToken(token) error", e);
}
if (userTokenOpt.isEmpty()) { if (userTokenOpt.isEmpty()) {
LOGGER.warn("[权限校验] token无效: {}", token); LOGGER.warn("[权限校验] token无效: {}", maskToken(token));
return ResponseEntity.status(401).body(Map.of("code", 401, "msg", "无效token")); return ResponseEntity.status(401).body(Map.of("code", 401, "msg", "无效token"));
} }
@ -84,7 +101,9 @@ public class UserQueryController {
for (Long roleId : roleIds) { for (Long roleId : roleIds) {
List<RoleFileRuleDTO> rules = userAppService.listRoleFileRules(roleId); List<RoleFileRuleDTO> rules = userAppService.listRoleFileRules(roleId);
LOGGER.info("[权限校验] 角色[{}]规则数={}", roleId, rules != null ? rules.size() : 0); LOGGER.info("[权限校验] 角色[{}]规则数={}", roleId, rules != null ? rules.size() : 0);
if (rules != null) allRules.addAll(rules); if (rules != null) {
allRules.addAll(rules);
}
} }
Optional<UserDTO> userDTO = userAppService.findById(userId); Optional<UserDTO> userDTO = userAppService.findById(userId);
@ -93,12 +112,14 @@ public class UserQueryController {
boolean hasPermission = false; boolean hasPermission = false;
for (RoleFileRuleDTO rule : allRules) { for (RoleFileRuleDTO rule : allRules) {
String pattern = rule.getFilePattern(); String pattern = rule.getFilePattern();
if (pattern == null) continue; if (StrUtil.isBlank(pattern)) {
continue;
}
LOGGER.info("[权限校验] 开始判断用户[{}]的角色规则[{}]是否允许访问: {}", userId, pattern, originalUri); LOGGER.info("[权限校验] 开始判断用户[{}]的角色规则[{}]是否允许访问: {}", userId, pattern, originalUri);
// 动态替换占位符 // 动态替换占位符
if (pattern.contains("${username}") && userName != null) { if (pattern.contains("${username}") && StrUtil.isNotBlank(userName)) {
pattern = pattern.replace("${username}", userName); pattern = pattern.replace("${username}", userName);
} }
@ -110,7 +131,18 @@ public class UserQueryController {
} }
// 先前缀匹配再正则匹配 // 先前缀匹配再正则匹配
if (originalUri.startsWith(pattern) || originalUri.matches(pattern)) { boolean matched = false;
if (originalUri.startsWith(pattern)) {
matched = true;
} else {
try {
matched = originalUri.matches(pattern);
} catch (Exception e) {
LOGGER.warn("[权限校验] 规则正则非法跳过。pattern={}, err={}", pattern, e.getMessage());
}
}
if (matched) {
LOGGER.info("[权限校验] 用户[{}]的角色规则[{}]允许访问: {}", userId, pattern, originalUri); LOGGER.info("[权限校验] 用户[{}]的角色规则[{}]允许访问: {}", userId, pattern, originalUri);
hasPermission = true; hasPermission = true;
break; break;
@ -126,6 +158,66 @@ public class UserQueryController {
} }
} }
private String firstNonBlank(String... values) {
if (values == null || values.length == 0) {
return null;
}
for (String value : values) {
if (StrUtil.isNotBlank(value)) {
return value.trim();
}
}
return null;
}
private String normalizeAuthorization(String authorization) {
if (StrUtil.isBlank(authorization)) {
return null;
}
String value = authorization.trim();
if (value.regionMatches(true, 0, "Bearer ", 0, 7)) {
return value.substring(7).trim();
}
return value;
}
private String extractCookie(String rawCookie, String cookieName) {
if (StrUtil.isBlank(rawCookie) || StrUtil.isBlank(cookieName)) {
return null;
}
String[] pairs = rawCookie.split(";");
for (String pair : pairs) {
if (StrUtil.isBlank(pair)) {
continue;
}
String item = pair.trim();
int idx = item.indexOf('=');
if (idx <= 0) {
continue;
}
String name = item.substring(0, idx).trim();
String value = item.substring(idx + 1).trim();
if (cookieName.equals(name)) {
return value;
}
}
return null;
}
private String maskToken(String token) {
if (StrUtil.isBlank(token)) {
return StrUtil.EMPTY;
}
if (token.length() <= 8) {
return "****";
}
return token.substring(0, 4) + "****" + token.substring(token.length() - 4);
}
@GetMapping("/username") @GetMapping("/username")
public ResponseEntity<?> getUsernameByToken( public ResponseEntity<?> getUsernameByToken(
@CookieValue(value = ConstantConfig.COOKIE_KEY, required = false) String cookieToken, @CookieValue(value = ConstantConfig.COOKIE_KEY, required = false) String cookieToken,