Shiro微服务适配:JWT与动态权限实践
Shiro在微服务与云原生环境中的适配实践
1. 无状态化支持:JWT替代Session方案
概念解析
在传统单体应用中,Shiro默认使用Session管理用户状态,但在微服务架构中,Session会导致以下问题:
- 服务间状态同步困难
- 横向扩展时Session共享开销
- 不符合RESTful无状态原则
JWT解决方案:
public class JWTRealm extends AuthorizingRealm {
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JWTToken;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
String jwt = (String) token.getPrincipal();
// 验证JWT签名、有效期等
DecodedJWT decoded = JWT.require(Algorithm.HMAC256("secret")).build().verify(jwt);
return new SimpleAuthenticationInfo(decoded.getSubject(), jwt, getName());
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 从JWT claims中解析权限信息
String jwt = principals.toString();
DecodedJWT decoded = JWT.decode(jwt);
Set<String> roles = parseRoles(decoded.getClaim("roles"));
return new SimpleAuthorizationInfo(roles);
}
}
实践建议
JWT配置要点:
- 使用HS256或RS256算法确保签名安全
- 设置合理的过期时间(建议2-4小时)
- 将用户基础信息和必要权限放入claims
- Token刷新机制:
2. 配置中心集成:动态权限规则加载
实现方案
微服务环境下,权限规则需要支持动态更新而无需重启服务:
@RefreshScope
public class DynamicFilterChainManager {
@Autowired
private ConfigService configService;
@Scheduled(fixedDelay = 30000)
public void refreshFilterChain() {
Map<String, String> newRules = configService.loadFilterRules();
DefaultFilterChainManager manager = getFilterChainManager();
manager.getFilterChains().clear();
newRules.forEach((url, filterChain) ->
manager.createChain(url, filterChain));
}
}
配置中心对接示例
配置中心类型 | 集成方式 | 监听机制 |
---|---|---|
Nacos | @NacosValue 注解+监听Namespace | ConfigService.listener |
Apollo | @ApolloConfig +ConfigChangeListener | 长轮询机制 |
Consul | Consul KV API + Watch | HTTP长轮询 |
最佳实践:
- 权限规则采用版本号控制,支持快速回滚
- 变更时先灰度发布到测试环境验证
- 结合Spring Cloud Bus实现集群级通知
3. 服务间鉴权:内部API的签名验证
签名验证流程
实现代码示例
public class ServiceAuthFilter extends AccessControlFilter {
@Override
protected boolean isAccessAllowed(ServletRequest request,
ServletResponse response, Object mappedValue) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
// 1. 获取必要参数
String serviceId = httpRequest.getHeader("X-Service-Id");
String timestamp = httpRequest.getHeader("X-Timestamp");
String signature = httpRequest.getHeader("X-Signature");
// 2. 时效性验证(防止重放攻击)
if (System.currentTimeMillis() - Long.parseLong(timestamp) > 300000) {
return false;
}
// 3. 重构签名并比对
String secret = getSecretByServiceId(serviceId);
String expectedSig = HmacUtils.hmacSha256Hex(secret,
serviceId + timestamp + httpRequest.getQueryString());
return expectedSig.equals(signature);
}
}
关键优化点:
- 使用非对称加密提升安全性(如RSA替换HMAC)
- 为每个服务分配独立密钥,定期轮换
- 结合服务网格(如Istio)实现双向TLS
4. Kubernetes适配:Pod身份认证场景
ServiceAccount集成方案
当Shiro运行在K8s Pod中时,可以利用ServiceAccount实现自动认证:
# shiro-config.yml
securityManager:
realms:
- type: com.example.K8sServiceAccountRealm
authenticator:
authenticationStrategy: atLeastOneSuccessful
public class K8sServiceAccountRealm extends AuthorizingRealm {
private final String namespace = System.getenv("NAMESPACE");
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
K8sToken k8sToken = (K8sToken) token;
// 调用K8s API验证Token
ApiClient client = Config.defaultClient();
AuthenticationV1Api api = new AuthenticationV1Api(client);
try {
TokenReview review = new TokenReview()
.spec(new TokenReviewSpec().token(k8sToken.getCredentials()));
TokenReview status = api.createTokenReview(review, null);
if (status.getStatus().getAuthenticated()) {
return new SimpleAuthenticationInfo(
status.getStatus().getUser().getUsername(),
k8sToken.getCredentials(),
getName());
}
} catch (ApiException e) {
throw new AuthenticationException("K8s验证失败", e);
}
return null;
}
}
典型云原生场景
- Init Container授权:
跨命名空间访问控制:
// 基于K8s RBAC的权限控制 @RequiresPermissions("namespace:dev:read") public List<Pod> getPods() { return k8sClient.pods().inNamespace("dev").list(); }
生产建议:
- 为不同环境(dev/test/prod)配置独立的ClusterRole
- 使用Vault动态管理敏感凭证
- 通过Admission Controller限制Pod的权限范围
总结对比
传统方案 | 云原生适配方案 | 优势对比 |
---|---|---|
Session会话 | JWT无状态令牌 | 消除服务端状态存储,便于水平扩展 |
静态权限配置 | 配置中心动态加载 | 实现秒级生效的权限规则更新 |
IP白名单 | 服务间签名验证 | 细粒度的服务身份认证 |
固定凭证 | K8s ServiceAccount | 自动化的凭证管理与轮换 |
通过以上改造,Shiro可以完美融入云原生技术栈,在保持API兼容性的同时获得微服务架构所需的弹性与可观测性能力。
评论已关闭