🎯 权限管理组件执行流程详解
🏗️ 组件架构图
┌─────────────────────────────────────────────────────────────┐
│ HTTP请求 │
└─────────────────────┬───────────────────────────────────────┘│
┌─────────────────────▼───────────────────────────────────────┐
│ SecureController │
│ - 获取当前用户ID │
│ - 统一错误处理 │
└─────────────────────┬───────────────────────────────────────┘│
┌─────────────────────▼───────────────────────────────────────┐
│ SecurityService (接口) │
│ - 业务语义化的权限检查方法 │
│ - canAccessUser(), canCreateProcurement()等 │
└─────────────────────┬───────────────────────────────────────┘│
┌─────────────────────▼───────────────────────────────────────┐
│ SecurityServiceImpl (实现) │
│ - 构建SecurityContext │
│ - 调用PermissionEngine │
│ - 异常处理 │
└─────────────────────┬───────────────────────────────────────┘│
┌─────────────────────▼───────────────────────────────────────┐
│ PermissionEngine (接口) │
│ - 权限计算的抽象接口 │
│ - checkPermission()方法 │
└─────────────────────┬───────────────────────────────────────┘│
┌─────────────────────▼───────────────────────────────────────┐
│ RoleBasedPermissionEngine (实现) │
│ - 具体的权限计算逻辑 │
│ - 基于角色的权限规则 │
└─────────────────────────────────────────────────────────────┘
🔄 完整执行流程
场景:BUYER用户想查看自己的信息
让我们跟踪一个完整的请求:GET /api/v1/users/123
第1步:SecureController - 安全控制器基类
// 任何继承SecureController的Controller
@RestController
class UserController(currentUserService: CurrentUserService,private val securityService: SecurityService // 👈 注入SecurityService接口
) : SecureController(currentUserService) {@GetMapping("/api/v1/users/{userId}")fun getUserInfo(@PathVariable userId: String): ResponseEntity<UserInfo> {// 1.1 获取当前用户ID(来自SecureController基类)val currentUserId = getCurrentUserId() // 返回 "123"// 1.2 调用SecurityService进行权限检查if (!securityService.canAccessUser(userId)) { // 👈 调用接口方法return createForbiddenResponse()}// 1.3 执行业务逻辑val userInfo = userService.getUserInfo(userId)return ResponseEntity.ok(userInfo)}
}
SecureController说:“我获取到当前用户ID是123,现在要检查是否可以访问用户123的信息,让我问问SecurityService!”
第2步:SecurityService - 权限服务接口
// SecurityService.kt - 接口定义
interface SecurityService {/*** 是否可以访问用户信息*/fun canAccessUser(userId: String?): Boolean // 👈 业务语义化的方法/*** 是否可以创建采购需求*/fun canCreateProcurement(): Boolean// ... 其他业务权限方法
}
SecurityService接口说:“我定义了所有业务权限检查的方法,具体实现由SecurityServiceImpl来完成!”
第3步:SecurityServiceImpl - 权限服务实现
// SecurityServiceImpl.kt - 具体实现
@Service("securityService")
class SecurityServiceImpl(private val currentUserService: CurrentUserService,private val permissionEngine: PermissionEngine // 👈 注入PermissionEngine接口
) : SecurityService {override fun canAccessUser(userId: String?): Boolean {// 3.1 调用通用权限检查方法return safeCheckPermission("user", "read", userId) // 👈 转换为通用格式}private fun safeCheckPermission(resource: String, // "user"action: String, // "read"targetId: String? // "123"): Boolean {return try {// 3.2 构建安全上下文val context = getCurrentSecurityContext() ?: return false// 3.3 调用权限引擎进行具体检查permissionEngine.checkPermission(context, resource, action, targetId) // 👈 委托给引擎} catch (e: Exception) {false // 异常时拒绝访问}}private fun getCurrentSecurityContext(): SecurityContext? {return try {val currentUserResult = currentUserService.getCurrentUser()if (!currentUserResult.isSuccess) return nullval currentUser = currentUserResult.data!!val role = Role.fromCode(currentUser.role.name) ?: return null// 3.4 创建SecurityContext对象SecurityContext(userId = currentUser.id.value.toString(), // "123"userRole = role, // Role.BUYERuserStatus = currentUser.status.name // "ACTIVE")} catch (e: Exception) {null}}
}
SecurityServiceImpl说:“我收到canAccessUser请求,让我构建安全上下文,然后调用权限引擎来做具体判断!”
第4步:PermissionEngine - 权限引擎接口
// PermissionEngine.kt - 权限计算引擎接口
interface PermissionEngine {/*** 检查权限*/fun checkPermission(context: SecurityContext, // 安全上下文resource: String, // 资源类型action: String, // 操作类型targetId: String? = null // 目标ID): Booleanfun getEngineVersion(): Stringfun getEngineDescription(): String
}
PermissionEngine接口说:“我定义了权限计算的标准接口,具体的计算逻辑由不同的实现来完成!”
第5步:RoleBasedPermissionEngine - 基于角色的权限引擎
// RoleBasedPermissionEngine.kt - 具体的权限计算实现
@Component
class RoleBasedPermissionEngine : PermissionEngine {override fun checkPermission(context: SecurityContext, // userId="123", userRole=BUYER, userStatus="ACTIVE"resource: String, // "user"action: String, // "read"targetId: String? // "123"): Boolean {// 5.1 基础检查:非活跃用户无权限if (!context.isActive()) {return false}// 5.2 管理员检查:管理员拥有所有权限if (context.isAdmin()) {return true}// 5.3 根据角色进行具体权限检查return when (context.userRole) {Role.BUYER -> checkBuyerPermission(context, resource, action, targetId) // 👈 BUYER角色Role.SELLER -> checkSellerPermission(context, resource, action, targetId)Role.FORWARDER -> checkForwarderPermission(context, resource, action, targetId)Role.SALES -> checkSalesPermission(context, resource, action, targetId)Role.SUPPORT -> checkSupportPermission(context, resource, action, targetId)Role.ADMIN -> true // 已在上面处理}}private fun checkBuyerPermission(context: SecurityContext, // userId="123", userRole=BUYERresource: String, // "user"action: String, // "read"targetId: String? // "123"): Boolean {return when (resource) {"user" -> when (action) {"read" -> context.canAccessUserData(targetId) // 👈 检查是否可以访问用户数据"write" -> context.canAccessUserData(targetId)else -> false}"procurement" -> when (action) {"create" -> true // BUYER可以创建采购需求"read" -> true // BUYER可以查看采购需求"write" -> canAccessOwnResource(context, targetId) // 只能修改自己的else -> false}// ... 其他资源else -> false}}
}
RoleBasedPermissionEngine说:“让我分析…用户123是BUYER角色,想读取用户123的信息,这是访问自己的数据,允许!”
🎭 各组件的具体职责
1. SecureController(安全控制器基类)
// 职责:提供安全基础设施
abstract class SecureController {protected fun getCurrentUserId(): String // 获取当前用户IDprotected fun resolveUserId(String?): String // 解析目标用户IDprotected fun createForbiddenResponse(): ResponseEntity // 创建403响应
}
角色:安全基础设施提供者
工作:获取用户身份、统一错误处理
2. SecurityService(权限服务接口)
// 职责:定义业务权限检查接口
interface SecurityService {fun canAccessUser(userId: String?): Boolean // 业务语义化fun canCreateProcurement(): Boolean // 业务语义化fun canModifyOrder(orderId: String?): Boolean // 业务语义化
}
角色:业务权限接口定义者
工作:提供清晰的业务语义化权限检查方法
3. SecurityServiceImpl(权限服务实现)
// 职责:协调和转换
@Service
class SecurityServiceImpl {private fun safeCheckPermission(resource, action, targetId): Boolean // 转换格式private fun getCurrentSecurityContext(): SecurityContext // 构建上下文
}
角色:协调者和转换器
工作:
- 将业务方法转换为通用权限检查
- 构建SecurityContext
- 异常处理
- 委托给权限引擎
4. PermissionEngine(权限引擎接口)
// 职责:定义权限计算接口
interface PermissionEngine {fun checkPermission(context, resource, action, targetId): Boolean // 通用权限检查
}
角色:权限计算接口定义者
工作:定义标准的权限计算接口,支持可插拔实现
5. RoleBasedPermissionEngine(基于角色的权限引擎)
// 职责:具体的权限计算逻辑
@Component
class RoleBasedPermissionEngine {private fun checkBuyerPermission(...): Boolean // BUYER角色权限private fun checkSellerPermission(...): Boolean // SELLER角色权限private fun checkAdminPermission(...): Boolean // ADMIN角色权限
}
角色:权限计算执行者
工作:
- 执行具体的权限计算逻辑
- 基于角色的权限规则
- 资源和操作的细粒度控制
🔄 数据流转过程
// 数据在各组件间的流转
HTTP请求: GET /api/v1/users/123↓
SecureController: getCurrentUserId() → "123"↓
SecurityService: canAccessUser("123")↓
SecurityServiceImpl: safeCheckPermission("user", "read", "123")↓
SecurityServiceImpl: getCurrentSecurityContext() → SecurityContext(userId="123", role=BUYER)↓
PermissionEngine: checkPermission(context, "user", "read", "123")↓
RoleBasedPermissionEngine: checkBuyerPermission(context, "user", "read", "123")↓
SecurityContext: canAccessUserData("123") → true (同一用户)↓
返回结果: true → 允许访问
🎯 为什么要这样设计?
1. 单一职责原则
- SecureController:只负责安全基础设施
- SecurityService:只负责业务权限接口
- SecurityServiceImpl:只负责协调和转换
- PermissionEngine:只负责权限计算接口
- RoleBasedPermissionEngine:只负责具体权限逻辑
2. 开闭原则
// 可以轻松添加新的权限引擎实现
@Component
class RuleBasedPermissionEngine : PermissionEngine {// 基于规则的权限计算
}@Component
class DatabasePermissionEngine : PermissionEngine {// 基于数据库配置的权限计算
}
3. 依赖倒置原则
// 高层模块依赖抽象,不依赖具体实现
class SecurityServiceImpl(private val permissionEngine: PermissionEngine // 依赖接口,不是具体实现
)
4. 接口隔离原则
// 不同层次的接口,职责明确
interface SecurityService { // 业务层接口fun canAccessUser(String?): Boolean
}interface PermissionEngine { // 权限计算接口fun checkPermission(...): Boolean
}
🎊 总结
这5个组件形成了一个完整的权限管理体系:
- SecureController = 安全门卫:检查身份,统一处理
- SecurityService = 业务顾问:提供业务语义化的权限检查
- SecurityServiceImpl = 协调员:转换格式,构建上下文,处理异常
- PermissionEngine = 权限计算标准:定义权限计算接口
- RoleBasedPermissionEngine = 权限计算器:执行具体的权限计算逻辑
就像一个完整的银行业务流程:
- 门卫(SecureController):检查身份证
- 业务顾问(SecurityService):了解业务需求
- 业务经理(SecurityServiceImpl):准备材料,协调各部门
- 审批标准(PermissionEngine):定义审批流程
- 审批员(RoleBasedPermissionEngine):根据规则做最终决定
这种设计让权限管理既灵活又可维护! 🎉
ps:
好问题!让我详细解释第4点和第5点的区别:
🤔 第4点和第5点的区别
📋 简单对比
步骤 | 组件 | 职责 | 具体工作 |
---|---|---|---|
第4点 | SecurityService | 权限服务 | 调用权限引擎,但不做具体判断 |
第5点 | RoleBasedPermissionEngine | 权限引擎 | 执行具体的权限计算逻辑 |
🔍 详细解析
第4点:SecurityService - 权限服务(中介者)
// SecurityServiceImpl.kt
@Service
class SecurityServiceImpl : SecurityService {override fun canAccessUser(userId: String?): Boolean {// 👈 这里只是调用权限引擎,自己不做判断return safeCheckPermission("user", "read", userId)}private fun safeCheckPermission(resource: String, action: String, targetId: String?): Boolean {return try {// 1. 获取当前用户的安全上下文val context = getCurrentSecurityContext() ?: return false// 2. 调用权限引擎进行检查(重点:这里只是调用,不判断)permissionEngine.checkPermission(context, resource, action, targetId)} catch (e: Exception) {false // 出错就拒绝访问}}
}
SecurityService说:“我收到了权限检查请求,让我准备好用户信息,然后交给权限引擎去判断!”
SecurityService的工作:
- 🔄 转换参数:将业务参数转换为权限引擎需要的格式
- 🛡️ 异常处理:捕获异常,确保系统安全
- 📋 获取上下文:准备当前用户的安全信息
- 📞 委托调用:把实际判断工作交给权限引擎
第5点:RoleBasedPermissionEngine - 权限引擎(实际判断者)
// RoleBasedPermissionEngine.kt
class RoleBasedPermissionEngine : PermissionEngine {override fun checkPermission(context: SecurityContext, // 用户123,BUYER角色resource: String, // "user"action: String, // "read"targetId: String? // "123"): Boolean {// 👈 这里才是真正的权限判断逻辑// 1. 非活跃用户无权限if (!context.isActive()) return false// 2. 管理员拥有所有权限if (context.isAdmin()) return true// 3. 根据角色检查权限return when (context.userRole) {Role.BUYER -> checkBuyerPermission(context, resource, action, targetId)// ... 其他角色}}private fun checkBuyerPermission(context: SecurityContext,resource: String,action: String,targetId: String?): Boolean {return when (resource) {"user" -> when (action) {"read" -> context.canAccessUserData(targetId) // 👈 具体的判断逻辑else -> false}else -> false}}
}
RoleBasedPermissionEngine说:“让我仔细分析…用户123是BUYER角色,想读取用户123的信息,这是访问自己的数据,允许!”
权限引擎的工作:
- 🧠 具体判断:执行真正的权限计算逻辑
- 📊 角色分析:根据用户角色决定权限范围
- 🎯 资源检查:判断是否可以访问特定资源
- ⚖️ 规则执行:应用具体的业务权限规则
🎭 用生活例子来理解
SecurityService = 银行前台接待员
- 客户:“我想查看我的账户信息”
- 接待员:“好的,让我帮您准备资料,然后请权限部门审核”
- 接待员的工作:
- 收集客户信息
- 准备审核材料
- 联系权限部门
- 处理异常情况
RoleBasedPermissionEngine = 银行权限审核部门
- 审核部门:“让我看看…您是账户持有人,想查看自己的账户,符合规定,批准!”
- 审核部门的工作:
- 分析客户身份
- 检查权限规则
- 做出最终决定
- 返回审核结果
🔄 完整的调用链
// 完整的调用过程
Controller.getUserInfo(userId: "123")↓
SecurityService.canAccessUser("123") // 👈 第4点:准备和调用↓
SecurityService.safeCheckPermission("user", "read", "123")↓
RoleBasedPermissionEngine.checkPermission(context, "user", "read", "123") // 👈 第5点:具体判断↓
RoleBasedPermissionEngine.checkBuyerPermission(...)↓
SecurityContext.canAccessUserData("123")↓
return true // 允许访问
🎯 为什么要分成两层?
1. 职责分离
// SecurityService:业务接口层
fun canAccessUser(userId: String?): Boolean // 业务语义清晰// PermissionEngine:权限计算层
fun checkPermission(context, resource, action, targetId): Boolean // 通用权限检查
2. 异常处理
// SecurityService负责异常处理
private fun safeCheckPermission(...): Boolean {return try {permissionEngine.checkPermission(...) // 可能抛异常} catch (e: Exception) {false // 统一处理异常}
}
3. 扩展性
// 可以轻松替换权限引擎
class SecurityServiceImpl(private val permissionEngine: PermissionEngine // 可以是不同的实现
) {// RoleBasedPermissionEngine// RuleBasedPermissionEngine // DatabasePermissionEngine
}
4. 测试友好
// 可以单独测试权限引擎
@Test
fun `BUYER角色应该可以访问自己的数据`() {val context = SecurityContext(userId = "123", userRole = Role.BUYER)val result = permissionEngine.checkPermission(context, "user", "read", "123")assertTrue(result)
}
🎊 总结
第4点和第5点的核心区别:
方面 | SecurityService(第4点) | RoleBasedPermissionEngine(第5点) |
---|---|---|
角色 | 中介者、协调者 | 执行者、判断者 |
职责 | 准备数据、调用引擎、处理异常 | 执行具体的权限计算逻辑 |
工作 | “我来帮你联系权限部门” | “我来判断你有没有权限” |
复杂度 | 简单的转发和异常处理 | 复杂的业务规则和权限计算 |
可替换性 | 相对稳定 | 可以有多种实现(基于角色、基于规则等) |
就像餐厅点餐:
- SecurityService = 服务员:接收订单,转给厨房,处理问题
- RoleBasedPermissionEngine = 厨师:根据菜谱制作具体的菜品
两者配合,形成了完整的权限检查流程! 🎉