fix: 修复超管角色鉴权

- 为用户注入 ROLE_{roleCode},支持 hasRole('super_admin')
- 超管接口鉴权由 hasAuthority('super_admin') 调整为 hasRole('super_admin')

Made-with: Cursor
This commit is contained in:
zhonghua 2026-04-01 14:01:27 +08:00
parent a714ec8cee
commit 3a3e3b752e
4 changed files with 31 additions and 14 deletions

View File

@ -30,7 +30,7 @@ public class PermissionController {
@PostMapping @PostMapping
@Operation(summary = "创建权限") @Operation(summary = "创建权限")
@PreAuthorize("hasAuthority('super_admin')") @PreAuthorize("hasRole('super_admin')")
public Result<PermissionDetailVO> create( public Result<PermissionDetailVO> create(
@AuthenticationPrincipal UserPrincipal userPrincipal, @AuthenticationPrincipal UserPrincipal userPrincipal,
@RequestBody @Validated CreatePermissionDTO dto) { @RequestBody @Validated CreatePermissionDTO dto) {
@ -73,7 +73,7 @@ public class PermissionController {
@PutMapping("/{id}") @PutMapping("/{id}")
@Operation(summary = "更新权限") @Operation(summary = "更新权限")
@PreAuthorize("hasAuthority('super_admin')") @PreAuthorize("hasRole('super_admin')")
public Result<PermissionDetailVO> update( public Result<PermissionDetailVO> update(
@AuthenticationPrincipal UserPrincipal userPrincipal, @AuthenticationPrincipal UserPrincipal userPrincipal,
@PathVariable Long id, @PathVariable Long id,
@ -85,7 +85,7 @@ public class PermissionController {
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
@Operation(summary = "删除权限") @Operation(summary = "删除权限")
@PreAuthorize("hasAuthority('super_admin')") @PreAuthorize("hasRole('super_admin')")
public Result<Void> delete( public Result<Void> delete(
@PathVariable Long id) { @PathVariable Long id) {
permissionService.delete(id); permissionService.delete(id);

View File

@ -42,7 +42,7 @@ public class UserController {
@GetMapping("/stats") @GetMapping("/stats")
@Operation(summary = "用户统计(仅超管)") @Operation(summary = "用户统计(仅超管)")
@PreAuthorize("hasAuthority('super_admin')") @PreAuthorize("hasRole('super_admin')")
public Result<UserStatsVO> getStats() { public Result<UserStatsVO> getStats() {
UserStatsVO result = userService.getStats(); UserStatsVO result = userService.getStats();
return Result.success(result); return Result.success(result);

View File

@ -3,6 +3,7 @@ package com.lesingle.creation.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lesingle.creation.common.security.UserPrincipal; import com.lesingle.creation.common.security.UserPrincipal;
import com.lesingle.creation.entity.Permission; import com.lesingle.creation.entity.Permission;
import com.lesingle.creation.entity.Role;
import com.lesingle.creation.entity.Tenant; import com.lesingle.creation.entity.Tenant;
import com.lesingle.creation.entity.User; import com.lesingle.creation.entity.User;
import com.lesingle.creation.entity.UserRole; import com.lesingle.creation.entity.UserRole;
@ -10,6 +11,7 @@ import com.lesingle.creation.entity.RolePermission;
import com.lesingle.creation.mapper.TenantMapper; import com.lesingle.creation.mapper.TenantMapper;
import com.lesingle.creation.mapper.UserMapper; import com.lesingle.creation.mapper.UserMapper;
import com.lesingle.creation.mapper.UserRoleMapper; import com.lesingle.creation.mapper.UserRoleMapper;
import com.lesingle.creation.mapper.RoleMapper;
import com.lesingle.creation.mapper.RolePermissionMapper; import com.lesingle.creation.mapper.RolePermissionMapper;
import com.lesingle.creation.mapper.PermissionMapper; import com.lesingle.creation.mapper.PermissionMapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -20,10 +22,11 @@ import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -38,6 +41,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
private final UserMapper userMapper; private final UserMapper userMapper;
private final TenantMapper tenantMapper; private final TenantMapper tenantMapper;
private final UserRoleMapper userRoleMapper; private final UserRoleMapper userRoleMapper;
private final RoleMapper roleMapper;
private final RolePermissionMapper rolePermissionMapper; private final RolePermissionMapper rolePermissionMapper;
private final PermissionMapper permissionMapper; private final PermissionMapper permissionMapper;
@ -89,10 +93,21 @@ public class UserDetailsServiceImpl implements UserDetailsService {
List<UserRole> userRoles = userRoleMapper.selectList(new LambdaQueryWrapper<UserRole>() List<UserRole> userRoles = userRoleMapper.selectList(new LambdaQueryWrapper<UserRole>()
.eq(UserRole::getUserId, user.getId())); .eq(UserRole::getUserId, user.getId()));
// 查询角色权限 // 角色编码 -> ROLE_xxx hasRole('super_admin') 等使用
LinkedHashSet<String> authorityStrings = new LinkedHashSet<>();
List<String> permissionCodes = new ArrayList<>(); List<String> permissionCodes = new ArrayList<>();
if (!userRoles.isEmpty()) { if (!userRoles.isEmpty()) {
List<Long> roleIds = userRoles.stream().map(UserRole::getRoleId).collect(Collectors.toList()); List<Long> roleIds = userRoles.stream().map(UserRole::getRoleId).distinct().collect(Collectors.toList());
List<Role> roles = roleMapper.selectList(
new LambdaQueryWrapper<Role>()
.in(Role::getId, roleIds)
.eq(Role::getDeleted, 0));
for (Role role : roles) {
if (StringUtils.hasText(role.getCode())) {
authorityStrings.add("ROLE_" + role.getCode());
}
}
List<RolePermission> rolePermissions = rolePermissionMapper.selectList( List<RolePermission> rolePermissions = rolePermissionMapper.selectList(
new LambdaQueryWrapper<RolePermission>() new LambdaQueryWrapper<RolePermission>()
.in(RolePermission::getRoleId, roleIds) .in(RolePermission::getRoleId, roleIds)
@ -109,16 +124,17 @@ public class UserDetailsServiceImpl implements UserDetailsService {
); );
permissionCodes = permissions.stream() permissionCodes = permissions.stream()
.map(Permission::getCode) .map(Permission::getCode)
.filter(StringUtils::hasText)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
} }
authorityStrings.addAll(permissionCodes);
// 构建 authorities List<SimpleGrantedAuthority> authorities = authorityStrings.stream()
List<SimpleGrantedAuthority> authorities = permissionCodes.stream() .map(SimpleGrantedAuthority::new)
.map(code -> new SimpleGrantedAuthority(code))
.collect(Collectors.toList()); .collect(Collectors.toList());
log.debug("用户 {} 的权限列表{}", user.getUsername(), permissionCodes); log.debug("用户 {} 的角色与权限:{}", user.getUsername(), authorityStrings);
// 构建 UserPrincipal 对象包含用户 ID租户 ID租户编码等信息 // 构建 UserPrincipal 对象包含用户 ID租户 ID租户编码等信息
UserPrincipal userPrincipal = new UserPrincipal( UserPrincipal userPrincipal = new UserPrincipal(

View File

@ -128,9 +128,10 @@ public class SecurityUtils {
return false; return false;
} }
// 检查是否有 super_admin 角色 // 超管角色ROLE_super_admin UserDetailsServiceImpl 中角色编码一致
return authentication.getAuthorities().stream() return authentication.getAuthorities().stream()
.anyMatch(grantedAuthority -> "ROLE_super_admin".equals(grantedAuthority.getAuthority())); .anyMatch(a -> "ROLE_super_admin".equals(a.getAuthority())
|| "super_admin".equals(a.getAuthority()));
} }
/** /**