在 Controller 方法上使用 @PreAuthorize 注解进行权限校验:
@RestController
@RequestMapping("/api/exam")
public class ExamController {
// 示例1: 检查是否有特定权限
@PreAuthorize("hasAuthority('exam:list')")
@PostMapping("/page")
public RestResult<?> getExamsByCondition(@RequestBody ExamQueryVO queryVO) {
// 只有拥有 'exam:list' 权限的用户才能访问
// ...
}
// 示例2: 检查是否有多个权限之一(OR关系)
@PreAuthorize("hasAnyAuthority('exam:create', 'exam:add')")
@PostMapping("/create")
public RestResult<?> createExam(@RequestBody ExamCreateVO createVO) {
// 拥有 'exam:create' 或 'exam:add' 权限的用户可以访问
// ...
}
// 示例3: 检查是否同时拥有多个权限(AND关系)
@PreAuthorize("hasAuthority('exam:update') and hasAuthority('exam:verify')")
@PostMapping("/update")
public RestResult<?> updateExam(@RequestBody ExamUpdateVO updateVO) {
// 必须同时拥有 'exam:update' 和 'exam:verify' 权限
// ...
}
// 示例4: 复杂表达式
@PreAuthorize("hasAuthority('exam:delete') or hasRole('ADMIN')")
@PostMapping("/delete/{id}")
public RestResult<?> deleteExam(@PathVariable String id) {
// 拥有 'exam:delete' 权限或者是 ADMIN 角色的用户可以访问
// ...
}
}
doctor_menu 表结构:
CREATE TABLE doctor_menu (
id VARCHAR(50) PRIMARY KEY,
name VARCHAR(100),
perms VARCHAR(255), -- 权限标识,如 'exam:list,exam:create'
parent_id VARCHAR(50),
status VARCHAR(10),
...
);
示例数据:
-- 医生菜单权限
INSERT INTO doctor_menu (id, name, perms, status) VALUES
('1', '检查管理', 'exam:list,exam:view', '1'),
('2', '报告管理', 'report:list,report:create', '1'),
('6', '申请医生', 'application:create,application:cancel', '1');
-- 医生角色配置
UPDATE doctors SET doctor_role = '1,2,6' WHERE id = 1;
建议使用 模块:操作 的格式:
exam:list - 检查列表查询exam:view - 检查详情查看exam:create - 创建检查exam:update - 更新检查exam:delete - 删除检查report:list - 报告列表report:create - 创建报告POST /auth/login
Headers:
Content-Type: application/json
platform: doctor # 可选: doctor/manage,不传则返回所有权限
Body:
{
"username": "doctor001",
"password": "123456"
}
{
"code": 200,
"message": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzUxMiJ9...", // JWT token(包含权限)
"userInfo": { ... },
"doctorInfo": {
"id": 1,
"doctorRole": "1,2,6",
"permissions": [
"exam:list",
"exam:view",
"report:list",
"report:create",
"application:create",
"application:cancel"
]
}
}
}
Token 中包含的 claims:
{
"username": "doctor001",
"userId": 1,
"permissions": "exam:list,exam:view,report:list,report:create" // 逗号分隔
}
GET /api/exam/page
Headers:
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9...
Content-Type: application/json
1. JwtAuthenticationFilter 拦截请求
↓
2. 从 Authorization header 提取 token
↓
3. JwtUtil.parseUserFromToken(token) 解析 token
↓
4. 从 token claims 中提取 permissions(逗号分隔字符串)
↓
5. 转换为 List<String> permissions
↓
6. 创建 LoginUser(user, permissions)
↓
7. 设置到 SecurityContext
↓
8. @PreAuthorize 注解检查权限
↓
9. 有权限 → 执行方法;无权限 → 403 Forbidden
{
"code": 403,
"message": "权限不足",
"data": null
}
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(AccessDeniedException.class)
public RestResult<?> handleAccessDeniedException(AccessDeniedException e) {
return RestResult.error(403, "权限不足");
}
}
application.yml 配置模块:操作 格式,便于管理确保 SecurityConfig 已启用方法级别安全:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 启用 @PreAuthorize
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// ...
}