fix(auth): harden confidential knowledge access checks and sensitivity filtering

This commit is contained in:
2026-02-09 17:09:34 +08:00
parent 71f8f7d1c3
commit 2f8645a011
19 changed files with 383 additions and 80 deletions

View File

@@ -14,11 +14,23 @@ import java.util.Objects;
@Service
public class ResourceAccessService {
public static final String ADMIN_ROLE_CODE = "ROLE_ADMIN";
public static final String VIEW_CONFIDENTIAL_PERMISSION = "knowledge:view-confidential";
public static final String CONFIDENTIAL_SENSITIVITY = "CONFIDENTIAL";
public boolean isAdmin() {
return RequestUserContextHolder.hasRole(ADMIN_ROLE_CODE);
}
/**
* 判断当前用户是否有权查看保密知识
*/
public boolean canViewConfidential() {
if (isAdmin()) {
return true;
}
return RequestUserContextHolder.hasPermission(VIEW_CONFIDENTIAL_PERMISSION);
}
public String getCurrentUserId() {
return RequestUserContextHolder.getCurrentUserId();
}

View File

@@ -15,19 +15,21 @@ public class RequestUserContext {
private final String userId;
private final String username;
private final List<String> roles;
private final List<String> permissions;
private RequestUserContext(String userId, String username, List<String> roles) {
private RequestUserContext(String userId, String username, List<String> roles, List<String> permissions) {
this.userId = userId;
this.username = username;
this.roles = roles == null ? Collections.emptyList() : List.copyOf(roles);
this.permissions = permissions == null ? Collections.emptyList() : List.copyOf(permissions);
}
public static RequestUserContext of(String userId, String username, List<String> roles) {
return new RequestUserContext(userId, username, roles);
public static RequestUserContext of(String userId, String username, List<String> roles, List<String> permissions) {
return new RequestUserContext(userId, username, roles, permissions);
}
public static RequestUserContext empty() {
return new RequestUserContext(null, null, Collections.emptyList());
return new RequestUserContext(null, null, Collections.emptyList(), Collections.emptyList());
}
public boolean hasRole(String roleCode) {
@@ -36,5 +38,12 @@ public class RequestUserContext {
}
return roles.stream().anyMatch(role -> StringUtils.hasText(role) && Objects.equals(role.trim(), roleCode));
}
public boolean hasPermission(String permissionCode) {
if (!StringUtils.hasText(permissionCode)) {
return false;
}
return permissions.stream().anyMatch(p -> StringUtils.hasText(p) && Objects.equals(p.trim(), permissionCode));
}
}

View File

@@ -42,6 +42,19 @@ public final class RequestUserContextHolder {
.anyMatch(role -> StringUtils.hasText(role) && roleCode.equalsIgnoreCase(role.trim()));
}
public static List<String> getCurrentPermissions() {
List<String> permissions = get().getPermissions();
return permissions == null ? Collections.emptyList() : permissions;
}
public static boolean hasPermission(String permissionCode) {
if (!StringUtils.hasText(permissionCode)) {
return false;
}
return getCurrentPermissions().stream()
.anyMatch(p -> StringUtils.hasText(p) && permissionCode.equals(p.trim()));
}
public static void clear() {
USER_CONTEXT_HOLDER.remove();
}

View File

@@ -18,13 +18,15 @@ public class RequestUserContextInterceptor implements HandlerInterceptor {
private static final String HEADER_USER_ID = "X-User-Id";
private static final String HEADER_USER_NAME = "X-User-Name";
private static final String HEADER_USER_ROLES = "X-User-Roles";
private static final String HEADER_USER_PERMISSIONS = "X-User-Permissions";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String userId = normalizeValue(request.getHeader(HEADER_USER_ID));
String username = normalizeValue(request.getHeader(HEADER_USER_NAME));
List<String> roleCodes = parseRoleCodes(request.getHeader(HEADER_USER_ROLES));
RequestUserContextHolder.set(RequestUserContext.of(userId, username, roleCodes));
List<String> roleCodes = parseCommaSeparatedValues(request.getHeader(HEADER_USER_ROLES));
List<String> permissionCodes = parseCommaSeparatedValues(request.getHeader(HEADER_USER_PERMISSIONS));
RequestUserContextHolder.set(RequestUserContext.of(userId, username, roleCodes, permissionCodes));
return true;
}
@@ -40,11 +42,11 @@ public class RequestUserContextInterceptor implements HandlerInterceptor {
return value.trim();
}
private List<String> parseRoleCodes(String roleHeader) {
if (!StringUtils.hasText(roleHeader)) {
private List<String> parseCommaSeparatedValues(String header) {
if (!StringUtils.hasText(header)) {
return Collections.emptyList();
}
return Arrays.stream(roleHeader.split(","))
return Arrays.stream(header.split(","))
.map(String::trim)
.filter(StringUtils::hasText)
.toList();