在 Spring Security 中,权限控制是保障系统安全的重要环节。本文将详细解析三个核心安全注解:@RequiresAuthentication
、@RequiresPermissions
和 @RequiresRoles
的异同点,并提供代码示例。
一、注解概述
@RequiresAuthentication
- 作用:要求用户必须已认证(登录)才能访问该方法或类
- 级别:最基本的权限控制
- 特点:不关心用户的具体权限或角色,只验证是否登录
@RequiresPermissions
- 作用:要求用户必须拥有指定的权限才能访问
- 级别:细粒度的权限控制
- 特点:基于权限字符串进行验证,灵活性高
@RequiresRoles
- 作用:要求用户必须属于指定的角色才能访问
- 级别:粗粒度的权限控制
- 特点:基于角色进行验证,通常角色会关联一组权限
二、异同点对比
特性 | RequiresAuthentication | RequiresPermissions | RequiresRoles |
验证内容 | 是否认证 | 特定权限 | 特定角色 |
粒度 | 最粗 | 最细 | 中等 |
应用场景 | 所有需登录的接口 | 具体操作权限控制 | 角色分类控制 |
是否可组合使用 | 是 | 是 | 是 |
默认错误处理 | 抛出AuthorizationException | 抛出AuthorizationException | 抛出AuthorizationException |
三、代码示例
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 "系统设置(需登录+管理员角色+配置权限)";
}
}
四、高级用法与注意事项
- 逻辑关系:
- 多个注解同时使用时是”与”关系
- 同一注解多个值是”或”关系(如
@RequiresRoles({"admin", "superadmin"})
)
- 自定义错误处理:
@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
实现细粒度控制 - 角色用于用户分类,权限用于功能控制
- 复杂场景可以组合使用多个注解
- 优先使用