You've already forked DataMate
fix(auth): harden confidential knowledge access checks and sensitivity filtering
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user