SecurityUtils 使用示例

场景一:获取用户信息

1.1 获取用户(可能为 null)

@GetMapping("/user/info")
public ResponseEntity<?> getUserInfo() {
    LoginUserVO user = SecurityUtils.getLoginUser();

    if (user == null) {
        return ResponseEntity.ok(Map.of("message", "请先登录"));
    }

    return ResponseEntity.ok(user);
}

1.2 获取用户(必须登录)

@PostMapping("/like")
public ResponseEntity<?> likeArticle(@RequestParam Long articleId) {
    // 此方法需要用户已登录
    LoginUserVO user = SecurityUtils.requireLoginUser();  // 未登录时抛异常
    Long userId = user.getId();

    articleService.like(articleId, userId);
    return ResponseEntity.ok("点赞成功");
}

1.3 简化获取用户 ID

@PostMapping("/comment")
public ResponseEntity<?> createComment(@RequestBody CommentRequest request) {
    // 直接获取用户 ID(简化写法)
    Long userId = SecurityUtils.requireUserId();

    Comment comment = new Comment();
    comment.setUserId(userId);
    comment.setContent(request.getContent());

    commentService.save(comment);
    return ResponseEntity.ok("评论成功");
}

场景二:权限校验(失败抛异常)

2.1 单个权限检查

@PostMapping("/users")
public ResponseEntity<?> createUser(@RequestBody CreateUserRequest request) {
    // 需要 system:user:add 权限,没有则抛异常
    SecurityUtils.checkPermission("system:user:add");

    User user = userService.createUser(request);
    return ResponseEntity.ok(user);
}

2.2 多权限检查(AND 逻辑)

@PostMapping("/publish-article")
public ResponseEntity<?> publishArticle(@RequestBody ArticleRequest request) {
    // 需要同时拥有 content:create 和 content:publish 权限
    SecurityUtils.checkPermission("content:create", "content:publish");

    Article article = articleService.createAndPublish(request);
    return ResponseEntity.ok(article);
}

2.3 多权限检查(OR 逻辑)

@PostMapping("/review-content")
public ResponseEntity<?> reviewContent(@RequestBody ReviewRequest request) {
    // 拥有任一权限即可:审核或发布权限
    SecurityUtils.checkAnyPermission("content:review", "content:publish");

    contentService.review(request);
    return ResponseEntity.ok("审核成功");
}

2.4 角色检查

@GetMapping("/admin/dashboard")
public ResponseEntity<?> getAdminDashboard() {
    // 需要 admin 角色
    SecurityUtils.checkRole("admin");

    return ResponseEntity.ok(adminService.getDashboard());
}

2.5 多角色检查(OR 逻辑)

@GetMapping("/system/logs")
public ResponseEntity<?> getSystemLogs() {
    // 拥有任一角色即可:管理员或超级管理员
    SecurityUtils.checkAnyRole("admin", "super_admin");

    return ResponseEntity.ok(logService.getLogs());
}

场景三:权限判断(返回 boolean)

3.1 条件显示功能

@GetMapping("/article/{id}")
public ResponseEntity<?> getArticle(@PathVariable Long id) {
    Article article = articleService.getById(id);

    // 判断当前用户是否可以编辑此文章
    boolean canEdit = SecurityUtils.hasPermission("content:edit")
                    && article.getUserId().equals(SecurityUtils.getUserId());

    // 判断当前用户是否是管理员
    boolean isAdmin = SecurityUtils.isAdmin();

    return ResponseEntity.ok(Map.of(
        "article", article,
        "canEdit", canEdit,
        "isAdmin", isAdmin
    ));
}

3.2 动态菜单根据权限显示

@GetMapping("/menu")
public ResponseEntity<?> getMenu() {
    List<MenuItem> menus = new ArrayList<>();

    // 基础菜单(所有人都有)
    menus.add(new MenuItem("首页", "/home"));
    menus.add(new MenuItem("个人资料", "/profile"));

    // 根据权限添加菜单
    if (SecurityUtils.hasPermission("content:create")) {
        menus.add(new MenuItem("创建内容", "/create"));
    }

    if (SecurityUtils.hasPermission("content:review")) {
        menus.add(new MenuItem("内容审核", "/review"));
    }

    if (SecurityUtils.isAdmin()) {
        menus.add(new MenuItem("用户管理", "/admin/users"));
        menus.add(new MenuItem("系统配置", "/admin/config"));
    }

    return ResponseEntity.ok(menus);
}

场景四:数据级权限(个人隐私数据)

4.1 只能查看自己的信息

@GetMapping("/user/{userId}/profile")
public ResponseEntity<?> getProfile(@PathVariable Long userId) {
    // 检查:只有本人或管理员才能查看个人资料
    SecurityUtils.checkSelfOrAdmin(userId);

    UserVO profile = userService.getProfile(userId);
    return ResponseEntity.ok(profile);
}

4.2 修改个人信息

@PutMapping("/user/{userId}/profile")
public ResponseEntity<?> updateProfile(
        @PathVariable Long userId,
        @RequestBody UpdateProfileRequest request) {
    // 权限检查:只能修改自己的信息
    SecurityUtils.checkSelfOrAdmin(userId);

    userService.updateProfile(userId, request);
    return ResponseEntity.ok("修改成功");
}

4.3 删除账户

@DeleteMapping("/user/{userId}")
public ResponseEntity<?> deleteAccount(@PathVariable Long userId) {
    // 权限检查:只有本人或超级管理员可以删除账户
    SecurityUtils.checkSelfOrAnyAdmin(userId);

    userService.deleteAccount(userId);
    return ResponseEntity.ok("账户已删除");
}

场景五:资源所有权检查

5.1 删除自己的文章

@Service
public class ArticleService {

    public void deleteArticle(Long articleId) {
        Article article = articleRepository.findById(articleId);
        if (article == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "文章不存在");
        }

        // 检查所有权:只有创建者能删除
        SecurityUtils.checkOwner(article.getUserId());

        articleRepository.delete(article);
        log.info("文章删除成功,articleId: {}", articleId);
    }
}

5.2 删除评论

@Service
public class CommentService {

    public void deleteComment(Long commentId) {
        Comment comment = commentRepository.findById(commentId);
        if (comment == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "评论不存在");
        }

        // 权限检查:评论作者或文章作者或管理员可以删除
        Long currentUserId = SecurityUtils.requireUserId();
        Long commentAuthorId = comment.getUserId();

        Article article = articleRepository.findById(comment.getArticleId());
        Long articleAuthorId = article.getUserId();

        boolean isCommentAuthor = currentUserId.equals(commentAuthorId);
        boolean isArticleAuthor = currentUserId.equals(articleAuthorId);
        boolean isAdmin = SecurityUtils.isAdmin();

        if (!isCommentAuthor && !isArticleAuthor && !isAdmin) {
            throw new BusinessException(ErrorCode.FORBIDDEN, "无权删除此评论");
        }

        commentRepository.delete(comment);
    }
}

场景六:Service 层权限检查

6.1 在 Service 中检查权限

@Service
@Slf4j
public class OrderService {

    /**
     * 创建订单 - 在 Service 中检查权限
     */
    public OrderVO createOrder(CreateOrderRequest request) {
        // 检查权限(也可以在 Controller 中检查)
        SecurityUtils.checkPermission("order:create");

        Long userId = SecurityUtils.requireUserId();

        Order order = new Order();
        order.setUserId(userId);
        order.setItems(request.getItems());

        orderRepository.save(order);
        log.info("订单创建成功,userId: {}, orderId: {}", userId, order.getId());

        return OrderVO.fromEntity(order);
    }

    /**
     * 修改订单 - 数据级权限检查
     */
    public void updateOrder(Long orderId, UpdateOrderRequest request) {
        Order order = orderRepository.findById(orderId);
        if (order == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "订单不存在");
        }

        // 检查权限:只有订单所有者或管理员可以修改
        SecurityUtils.checkSelfOrAdmin(order.getUserId());

        order.setStatus(request.getStatus());
        orderRepository.save(order);

        log.info("订单修改成功,orderId: {}", orderId);
    }

    /**
     * 查看订单 - 数据级权限检查
     */
    public OrderVO getOrder(Long orderId) {
        Order order = orderRepository.findById(orderId);
        if (order == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "订单不存在");
        }

        // 检查权限:只有订单所有者或管理员可以查看
        SecurityUtils.checkSelfOrAdmin(order.getUserId());

        return OrderVO.fromEntity(order);
    }

    /**
     * 导出订单 - 权限检查
     */
    public void exportOrders(List<Long> orderIds) {
        // 检查是否有导出权限
        if (!SecurityUtils.hasPermission("order:export")) {
            throw new BusinessException(ErrorCode.FORBIDDEN, "没有导出权限");
        }

        // 执行导出逻辑
        performExport(orderIds);
    }
}

场景七:认证状态检查

7.1 需要登录的操作

@PostMapping("/favorite")
public ResponseEntity<?> addFavorite(@RequestParam Long articleId) {
    // 强制要求用户已登录
    SecurityUtils.requireAuthenticated();

    Long userId = SecurityUtils.getUserId();
    favoriteService.addFavorite(userId, articleId);

    return ResponseEntity.ok("已收藏");
}

7.2 不能登录的操作

@PostMapping("/auth/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
    // 防止重复登录
    SecurityUtils.requireNotAuthenticated();

    UserVO user = userService.login(request);
    return ResponseEntity.ok(user);
}

7.3 条件性功能

@GetMapping("/article/{id}")
public ResponseEntity<?> getArticle(@PathVariable Long id) {
    Article article = articleService.getById(id);

    Map<String, Object> response = new HashMap<>();
    response.put("article", article);

    // 只有已登录用户才能看到点赞按钮
    if (SecurityUtils.isAuthenticated()) {
        Long userId = SecurityUtils.getUserId();
        boolean liked = favoriteService.isLiked(userId, id);
        response.put("liked", liked);
        response.put("canComment", true);
    } else {
        response.put("message", "请登录后进行点赞和评论");
    }

    return ResponseEntity.ok(response);
}

最佳实践

DO(该做的)

  1. 使用 requireLoginUser() 而不是 getLoginUser()

    // ✅ 好:明确要求用户已登录
    LoginUserVO user = SecurityUtils.requireLoginUser();
    
    // ❌ 不好:需要额外的 null 检查
    LoginUserVO user = SecurityUtils.getLoginUser();
    if (user == null) { ... }
    
  2. 在 Controller 中进行权限校验

    // ✅ 好:权限校验在 Controller 层
    @PostMapping("/users")
    public ResponseEntity<?> createUser() {
        SecurityUtils.checkPermission("system:user:add");
        return ResponseEntity.ok(userService.createUser(...));
    }
    
  3. 在 Service 中进行数据级权限检查

    // ✅ 好:数据权限检查在 Service 层
    public void updateOrder(Long orderId) {
        Order order = orderRepository.findById(orderId);
        SecurityUtils.checkSelfOrAdmin(order.getUserId());
        // 执行更新
    }
    
  4. 使用具体的权限码

    // ✅ 好:使用常量避免拼写错误
    public static final String PERMISSION_USER_ADD = "system:user:add";
    
    SecurityUtils.checkPermission(PERMISSION_USER_ADD);
    

DON'T(不该做的)

  1. 直接使用 getLoginUser() 而忘记 null 检查
  2. 权限校验在多个地方重复
  3. 使用硬编码的权限字符串
  4. 忘记进行数据级权限检查

权限常量定义

public class PermissionConstants {
    // 用户管理
    public static final String USER_ADD = "system:user:add";
    public static final String USER_EDIT = "system:user:edit";
    public static final String USER_DELETE = "system:user:delete";
    public static final String USER_VIEW = "system:user:view";

    // 内容管理
    public static final String CONTENT_CREATE = "content:create";
    public static final String CONTENT_EDIT = "content:edit";
    public static final String CONTENT_DELETE = "content:delete";
    public static final String CONTENT_PUBLISH = "content:publish";
    public static final String CONTENT_REVIEW = "content:review";

    // 订单管理
    public static final String ORDER_CREATE = "order:create";
    public static final String ORDER_EXPORT = "order:export";
    public static final String ORDER_CANCEL = "order:cancel";
}

// 在 Controller 中使用
@PostMapping("/users")
public ResponseEntity<?> createUser() {
    SecurityUtils.checkPermission(PermissionConstants.USER_ADD);
    return ResponseEntity.ok(userService.createUser(...));
}

项目分区导航:⬅️ 03-权限校验最佳实践模型代码 | 04-SecurityUtils 使用示例 | ➡️ 05-权限控制模型