Skip to content

Security RBAC Plugin

对应模块: io.gitee.lcgyl:lcgyl-security-rbac-plugin

基于角色的访问控制 (RBAC) 模型实现,提供细粒度的权限管理能力。

✨ 特性

  • 多级模型 - 用户-角色-权限 标准模型
  • 动态鉴权 - 支持运行时修改权限配置
  • 注解驱动 - @RequiresPermissions, @RequiresRoles
  • 数据权限 - 支持基于数据范围的权限过滤

🚀 快速开始

依赖引入

gradle
implementation 'io.gitee.lcgyl:lcgyl-security-rbac-plugin:2.2.0'

配置

yaml
lcgyl:
  security:
    rbac:
      enabled: true
      cache-enabled: true
      cache-ttl: 5m

注解式权限控制

java
@RestController
@RequestMapping("/api/users")
public class UserController {

    // 需要单个权限
    @RequiresPermissions("user:create")
    @PostMapping
    public User createUser(@RequestBody CreateUserRequest request) {
        return userService.create(request);
    }
    
    // 需要多个权限(AND)
    @RequiresPermissions(value = {"user:read", "user:update"}, logical = Logical.AND)
    @PutMapping("/{id}")
    public User updateUser(@PathVariable String id, @RequestBody UpdateUserRequest request) {
        return userService.update(id, request);
    }
    
    // 需要任一权限(OR)
    @RequiresPermissions(value = {"user:delete", "admin:all"}, logical = Logical.OR)
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable String id) {
        userService.delete(id);
    }
    
    // 需要特定角色
    @RequiresRoles("ADMIN")
    @GetMapping("/all")
    public List<User> listAllUsers() {
        return userService.findAll();
    }
    
    // 需要多个角色(任一)
    @RequiresRoles(value = {"ADMIN", "MANAGER"}, logical = Logical.OR)
    @GetMapping("/department/{deptId}")
    public List<User> listDepartmentUsers(@PathVariable String deptId) {
        return userService.findByDepartment(deptId);
    }
}

编程式权限检查

java
@Service
public class OrderService {
    
    @Inject
    private PermissionChecker permissionChecker;
    
    public void cancelOrder(String orderId) {
        Order order = orderRepository.findById(orderId);
        
        // 检查是否有取消权限,或者是订单所有者
        if (!permissionChecker.hasPermission("order:cancel") 
            && !order.getUserId().equals(getCurrentUserId())) {
            throw new AccessDeniedException("无权取消此订单");
        }
        
        order.setStatus(OrderStatus.CANCELLED);
        orderRepository.save(order);
    }
    
    public void approveRefund(String orderId) {
        // 检查是否有任一权限
        if (!permissionChecker.hasAnyPermission("refund:approve", "finance:all")) {
            throw new AccessDeniedException("无退款审批权限");
        }
        // ...
    }
}

数据权限

java
@Service
public class DataPermissionService {
    
    @Inject
    private DataScopeResolver dataScopeResolver;
    
    // 自动过滤数据范围
    @DataPermission(scope = DataScope.DEPARTMENT)
    public List<Order> getOrders() {
        // 自动添加部门过滤条件
        return orderRepository.findAll();
    }
}

// 自定义数据范围
@DataPermission(
    scope = DataScope.CUSTOM,
    handler = OrderDataScopeHandler.class
)
public List<Order> getMyTeamOrders() {
    return orderRepository.findAll();
}

@Component
public class OrderDataScopeHandler implements DataScopeHandler {
    @Override
    public String getScopeSql(User user) {
        // 返回 SQL 条件
        return "created_by IN (SELECT id FROM users WHERE team_id = '" + user.getTeamId() + "')";
    }
}

权限数据模型

java
// 用户实体
@Entity
public class User {
    @Id
    private String id;
    private String username;
    
    @ManyToMany
    @JoinTable(name = "user_roles")
    private Set<Role> roles;
}

// 角色实体
@Entity
public class Role {
    @Id
    private String id;
    private String name;
    private String code;
    
    @ManyToMany
    @JoinTable(name = "role_permissions")
    private Set<Permission> permissions;
}

// 权限实体
@Entity
public class Permission {
    @Id
    private String id;
    private String name;
    private String code;  // 如: user:create, order:read
    private String resource;
    private String action;
}

动态权限加载

java
@Component
public class DatabasePermissionProvider implements PermissionProvider {
    
    @Inject
    private UserRepository userRepository;
    
    @Override
    public Set<String> getPermissions(String userId) {
        User user = userRepository.findById(userId);
        return user.getRoles().stream()
            .flatMap(role -> role.getPermissions().stream())
            .map(Permission::getCode)
            .collect(Collectors.toSet());
    }
    
    @Override
    public Set<String> getRoles(String userId) {
        User user = userRepository.findById(userId);
        return user.getRoles().stream()
            .map(Role::getCode)
            .collect(Collectors.toSet());
    }
}

Released under the Apache License 2.0