微服务中如何通过JWT实现user-service与hospital-service的权限联动?
微服务权限联动方案:user-service与hospital-service的协作实现
核心协作逻辑
基于JWT令牌的无状态身份传递是两个服务联动的核心:user-service负责签发包含用户身份、角色信息的JWT,hospital-service通过验证令牌合法性,解析出用户角色,进而完成权限校验。全程不需要跨服务频繁调用user-service,保证性能的同时实现解耦。
具体实现步骤
1. 客户端传递JWT令牌
用户在user-service完成登录后,获取到访问令牌(Access Token)。后续请求hospital-service的业务接口时,需在HTTP请求头中携带该令牌,格式为:
Authorization: Bearer <JWT_TOKEN>
2. hospital-service本地验证JWT合法性
hospital-service与user-service共享JWT签名密钥(比如对称加密的密钥,或非对称加密的公钥),直接在本地完成令牌验证:
- 验证令牌的签名是否有效,防止篡改
- 检查令牌是否过期
- 验证令牌的签发方(issuer)是否为可信的user-service
注:如果不想共享密钥,也可以调用user-service提供的令牌验证接口(比如
/api/auth/validate-token),但会增加跨服务调用开销,适合对密钥共享敏感的场景。
3. 解析用户身份并注入SecurityContext
验证通过后,解析JWT的Payload部分,提取关键信息:用户ID、角色列表(比如["RECEPTIONIST"]或["DOCTOR"]),然后将这些信息封装成用户认证对象,存入hospital-service的SecurityContext中,和user-service的授权逻辑保持一致。
4. 接口层权限校验
在hospital-service的业务接口上,通过权限注解或拦截器实现角色校验:
- 粗粒度权限:用Spring Security的
@PreAuthorize注解直接限制角色,比如添加医生的接口:@PostMapping("/doctors") @PreAuthorize("hasRole('RECEPTIONIST')") public ResponseEntity<Void> addDoctor(@RequestBody DoctorDTO doctor) { // 业务逻辑 } - 细粒度数据权限:比如医生只能查看自己负责的患者,可在业务逻辑中从
SecurityContext获取当前用户ID,过滤数据库查询条件:@GetMapping("/patients") @PreAuthorize("hasRole('DOCTOR')") public ResponseEntity<List<PatientDTO>> getMyPatients() { Long currentDoctorId = SecurityContextHolder.getContext().getAuthentication().getPrincipal().getId(); return patientRepository.findByDoctorId(currentDoctorId); }
特殊场景处理
- 角色变更:因为JWT是无状态的,一旦签发无法修改。如果user-service调整了用户角色,需让旧令牌失效(比如通过令牌黑名单),或等待令牌自然过期,用户重新登录获取包含新角色的令牌。
- 刷新令牌:客户端用刷新令牌向user-service获取新的访问令牌,hospital-service只需验证新令牌即可,无需感知刷新逻辑。
内容的提问来源于stack exchange,提问作者dsa14dfS
相关产品推荐
相关产品推荐

