在 Spring Security 中,权限控制是保障系统安全的重要环节。本文将详细解析三个核心安全注解:@RequiresAuthentication、@RequiresPermissions 和 @RequiresRoles 的异同点,并提供代码示例。
一、注解概述
@RequiresAuthentication
作用:要求用户必须已认证(登录)才能访问该方法或类
级别:最基本的权限控制
特点:不关心用户的具体权限或角色,只验证是否登录
@RequiresPermissions
作用:要求用户必须拥有指定的权限才能访问
级别:细粒度的权限控制
特点:基于权限字符串进行验证,灵活性高
@RequiresRoles
作用:要求用户必须属于指定的角色才能访问
级别:粗粒度的权限控制
特点:基于角色进行验证,通常角色会关联一组权限
二、异同点对比

三、代码示例
1.@RequiresAuthentication 示例
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AuthController {
@GetMapping("/profile")
@RequiresAuthentication
public String getUserProfile() {
return "用户个人资料(需登录访问)";
}
}
2.@RequiresPermissions 示例
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/document")
public class DocumentController {
@GetMapping("/{id}")
@RequiresPermissions("document:read")
public String readDocument(@PathVariable String id) {
return "读取文档ID: " + id;
}
@PostMapping
@RequiresPermissions("document:create")
public String createDocument() {
return "创建新文档";
}
}
3.@RequiresRoles 示例
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/admin")
public class AdminController {
@GetMapping("/dashboard")
@RequiresRoles("admin")
public String adminDashboard() {
return "管理员仪表盘";
}
@GetMapping("/audit")
@RequiresRoles({"admin", "auditor"})
public String auditLogs() {
return "审计日志(管理员或审计员可访问)";
}
}
4.组合使用
@RestController
@RequestMapping("/system")
public class SystemController {
@GetMapping("/settings")
@RequiresAuthentication
@RequiresRoles("admin")
@RequiresPermissions("system:configure")
public String systemSettings() {
return "系统设置(需登录+管理员角色+配置权限)";
}
}
四、高级用法与注意事项
1逻辑关系:
-
多个注解同时使用时是”与”关系
-
同一注解多个值是”或”关系(如@RequiresRoles({“admin”, “superadmin”}))
2自定义错误处理:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(AuthorizationException.class)
public ResponseEntity<String> handleAuthException(AuthorizationException e) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body("访问被拒绝: " + e.getMessage());
}
}
3.性能考虑
权限检查会在每次请求时执行
对于频繁访问的接口,考虑缓存权限信息
4.测试建议
@SpringBootTest
@AutoConfigureMockMvc
class SecurityAnnotationTest {
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser
void testRequiresAuthentication() throws Exception {
mockMvc.perform(get("/profile"))
.andExpect(status().isOk());
}
@Test
@WithMockUser(roles = "admin")
void testRequiresRoles() throws Exception {
mockMvc.perform(get("/admin/dashboard"))
.andExpect(status().isOk());
}
}
五、总结
选择依据:
-
只需验证登录状态 → @RequiresAuthentication
-
基于业务功能控制 → @RequiresPermissions
-
基于用户角色分类 → @RequiresRoles
最佳实践:
- 优先使用@RequiresPermissions实现细粒度控制
- 角色用于用户分类,权限用于功能控制
- 复杂场景可以组合使用多个注解



