安全认证
统一身份认证、服务间可信通信与全链路操作审计
完整测试代码参见:https://gitee.com/javafree-cloud/javafree2025-examples
1. 架构概览:三位一体的企业级零信任安全基座
在微服务与云原生架构日益普及的背景下,传统边界防护模型已无法满足现代应用对细粒度访问控制、端到端可追溯性与自动化合规的要求。JavaFreeCloud 基于“永不信任,始终验证”(Never Trust, Always Verify)的零信任原则,构建了覆盖 身份认证层、服务通信层、操作审计层 的三位一体安全体系:
| 安全维度 | 技术实现 | 核心价值 |
|---|---|---|
| 统一身份认证 | JWT + RS256 双 Token 模型 | 实现用户身份的无状态、标准化、高安全性管理 |
| 服务间可信通信 | HMAC-SHA256 对称签名机制 | 保障微服务与第三方系统调用的完整性、防重放与来源可信 |
| 全链路操作审计 | 异步日志采集 + 生命周期治理 | 满足 GDPR、等保、金融行业等强合规场景的可追溯要求 |
该体系不仅提供开箱即用的安全能力,更通过配置驱动、模块解耦、扩展点开放的设计,支持企业按需定制安全策略,实现安全与敏捷的平衡。
2. JWT 统一身份认证系统:基于非对称加密的标准化身份治理
2.1 架构设计与安全优势
JavaFreeCloud 采用 Access Token + Refresh Token 双令牌架构,严格遵循 OAuth 2.0 最佳实践,并针对企业级场景进行深度优化:
- Access Token(短期凭证)
- 有效期:7200 秒(2 小时)
- 签名算法:RS256(RSA-PKCS#1 v1.5 + SHA-256)
- 存储建议:前端内存(如 Vuex/Pinia),避免持久化存储
- 安全价值:短期有效大幅降低 Token 泄露后的攻击窗口;非对称签名确保即使公钥公开,也无法伪造 Token。
- Refresh Token(长期凭证)
- 有效期:86400 秒(1 天)
- 存储建议:HttpOnly + Secure Cookie(防 XSS 与中间人窃取)
- 体验价值:支持无感续签,用户无需频繁重新登录,提升产品可用性。
✅ 相较于对称签名(如 HS256)的优势:
- 私钥仅由认证中心(Auth Server)持有,资源服务器仅需公钥即可验签,密钥分发更安全
- 支持多资源服务器并行验签,无密钥同步风险
- 符合金融、政务等高安全等级场景的密钥隔离要求
2.2 密钥管理与部署实践
密钥通过内置工具 RsaKeyGenTool 生成,支持密码保护的 PKCS#8 格式私钥:
jwt:
private.key: classpath:app.key # 开发环境
# private.key: /opt/certs/app.key # 生产环境推荐
public.key: classpath:app.pub
private.key.password: "javafree-cloud-rsa-password"🔐 生产环境密钥治理建议:
- 私钥文件应部署于受控目录(如
/opt/certs/),权限设为600- 禁止将私钥打包进应用 Jar 包
- 高安全场景可集成 HSM(硬件安全模块)或 HashiCorp Vault 进行密钥托管
2.3 自定义传输协议规避前端兼容性风险
为规避浏览器或代理对标准 Authorization Header 的自动大小写转换(如转为 authorization),框架采用自定义 Header 名称:
jwt:
token:
token_name: Javafreeauthorization # 全小写,避免前端自动格式化
token_head: "Bearer "此设计确保 Token 在跨域、反向代理、CDN 等复杂网络环境下仍能被正确解析,显著提升生产环境稳定性。
2.4 精细化白名单与权限控制
通过 white_urls 显式声明免认证路径,遵循最小权限原则(Principle of Least Privilege):
jwt:
security:
white_urls:
- /auth/token
- /static/**
- /actuator/health
# 敏感路径如 /druid/** 应在生产环境移除2.5 JWT 验证客户端示例:快速集成与调试
为便于开发与测试,框架提供了完整的 JWT 客户端工具类。以下为验证 Token 并提取用户信息的完整示例:
// 文件:TestJwtValidation.java
package cn.javafree.cloud.jwt.client;
import cn.javafree.cloud.jwt.client.config.JwtClientConfig;
import cn.javafree.cloud.jwt.client.utils.JwtUtils;
public class TestJwtValidation {
private static final String JWT_TOKEN = "Bearer eyJhbGciOiJSUzI1NiJ9.xxxxx";
public static void main(String[] args) {
// 方式一:使用默认配置(从 classpath 加载公钥)
testWithDefaultConfig();
// 方式二:自定义配置(指定公钥路径)
testWithCustomConfig();
}
private static void testWithDefaultConfig() {
String token = JWT_TOKEN.startsWith("Bearer ") ?
JWT_TOKEN.substring(7) : JWT_TOKEN;
boolean valid = JwtUtils.isValid(token);
if (valid) {
JwtUserInfo userInfo = JwtUtils.getUserInfo(token);
System.out.println("Realname: " + userInfo.getRealname());
System.out.println("Email: " + userInfo.getEmail());
// 支持 ID、Phone、WorkNo、UserType、Category 等扩展字段
}
}
private static void testWithCustomConfig() {
JwtClientConfig config = new JwtClientConfig();
config.setPublicKeyPath("classpath:jwt/public-key.pem");
JwtClient client = new JwtClient(config);
boolean valid = client.isValid(token);
JwtUserInfo userInfo = client.getJwtUserInfo(token); // 类型安全封装
}
}💡 客户端能力亮点:
- 自动剥离
Bearer前缀,兼容标准与自定义传输格式JwtUserInfo提供类型安全的用户属性访问(ID、Realname、Email、Phone、WorkNo 等)- 支持动态公钥加载,适用于公钥轮换或远程获取场景
- 内置过期检查、角色解析、调试日志等实用功能
3. HMAC 服务间安全调用机制:轻量级 API 网关替代方案
3.1 设计目标与适用场景
在 Service Mesh 尚未全面落地的中大型企业中,HMAC 签名提供了一种轻量、高效、无侵入的服务间认证方案,适用于:
- 微服务 A → 微服务 B 的同步调用
- 第三方系统回调(如支付、短信平台)
- 后台批处理任务(ETL、定时同步)
其核心优势在于无状态、低延迟、高吞吐,无需维护会话或依赖中心化认证服务。
3.2 安全协议规范
客户端需按以下规则构造请求头(以 X-App- 为例):
| Header | 说明 | 安全作用 |
|---|---|---|
X-App-AccessKey | 调用方唯一标识 | 身份识别,支持多租户 |
X-App-Timestamp | Unix 时间戳(秒) | 防重放(结合时间窗口) |
X-App-Nonce | 16 字节随机字符串 | 防重放(唯一性校验) |
X-App-Signature | Base64(HMAC-SHA256(payload, secret)) | 防篡改、来源认证 |
签名 payload 格式:
{HTTP_METHOD}\n{REQUEST_PATH}\n{QUERY_OR_BODY}\n{TIMESTAMP}\n{NONCE}✅ HMAC-SHA256 的密码学优势:
- 抗碰撞性强,难以构造相同签名的不同请求
- 计算效率高,适合高频调用场景
- 服务端可通过 accessKey 动态查找对应 secret,支持多客户端密钥隔离
3.3 HMAC 客户端调用示例:标准 HTTP 集成
以下为使用 HmacAuthClient 发起带签名 GET 请求的完整测试代码:
// 文件:TestHmacAuthClient.java
package cn.javafree.cloud.jwt.client;
import cn.javafree.cloud.jwt.client.config.HmacAuthConfig;
public class TestHmacAuthClient {
public static void main(String[] args) {
// 1. 配置密钥(生产环境应从配置中心注入)
HmacAuthConfig config = new HmacAuthConfig();
config.setAccessKey("AK_30628108_837043_19C7");
config.setSecret("2B3BF99C4618C76C53D96AAAD9CA7A388910810B225F2F373612C6CE1B3D5BA1");
config.setHeaderPrefix("X-App-");
// 2. 创建客户端
HmacAuthClient client = new HmacAuthClient(config);
// 3. 构造请求(GET 请求无 body)
String path = "/sa-menu/getMenuById";
String query = "id=108718494781401";
Map<String, String> headers = client.buildHeaders("GET", path, query);
// 4. 发送 HTTP 请求(使用 Java 11+ HttpClient)
String fullUrl = "http://localhost:8090" + path + "?" + query;
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(fullUrl))
.GET()
.headers(headers.entrySet().stream()
.flatMap(e -> Stream.of(e.getKey(), e.getValue()))
.toArray(String[]::new))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status: " + response.statusCode());
System.out.println("Body: " + response.body());
}
}🛠️ 客户端设计亮点:
- 无依赖轻量级:仅依赖 JDK 11+ 标准库,无需额外 HTTP 客户端
- 自动签名生成:
buildHeaders()方法封装完整签名逻辑- 方法语义清晰:明确区分 GET(无 body)与 POST(含 body)的签名构造
- 生产就绪:支持从环境变量或配置中心安全注入密钥
3.4 配置安全最佳实践
hmac:
auth:
auth-header-prefix: X-App-
access-key: ${ACCESS_KEY} # 从环境变量注入
secret: ${HMAC_SECRET} # 严禁硬编码🛡️ 密钥生命周期管理建议:
- 通过配置中心(Nacos/Apollo)加密存储 secret
- 定期轮换密钥(≤90 天),支持新旧密钥并行过渡
- 为每个调用方分配独立密钥对,实现故障隔离与责任追溯
4. 登录日志全生命周期管理:满足强合规审计要求
4.1 审计内容与数据模型
系统自动记录每次认证尝试的关键元数据,形成结构化审计事件:
| 字段 | 类型 | 说明 |
|---|---|---|
username | String | 用户账号 |
ip_address | String | 客户端真实 IP(支持 XFF 解析) |
user_agent | String | 设备与浏览器指纹 |
login_time | LocalDateTime | 精确到毫秒 |
result | Enum | SUCCESS / FAILED(含失败原因) |
tenant_id | String | 多租户标识 |
该模型完全兼容 ISO/IEC 27001 A.12.4 与 等保 2.0 “安全审计” 控制项。
4.2 自动化清理与存储优化
accesslog:
retention-minutes: 1440 # 日志保留多少分钟 默认 24 小时 # 可配置保留周期(默认 30 天)
cleanup-cron: "0 0 2 * * ?" # 每日凌晨 2 点执行- 动态可调:支持运行时调整保留策略,灵活应对 GDPR(≥6 个月)、金融行业(≥5 年)等不同合规要求
- 低开销执行:基于 Spring Scheduler 的轻量级任务,不影响主业务性能
- 归档友好:日志实体
SysLoginLog支持无缝迁移至历史表或数据湖
5. 全链路访问日志审计:实现操作行为可追溯
5.1 日志采集策略
通过 AOP 切面自动拦截所有非白名单请求,采集关键上下文:
- 请求方法、URI、参数(敏感字段可脱敏)
- 用户身份(从 JWT 解析)
- 客户端 IP、User-Agent
- 响应状态码、处理耗时
- 业务操作类型(通过注解扩展)
5.2 高性能异步写入架构
accesslog:
storage: jpa # 支持 JPA(关系型)或 Elasticsearch(分析型)
thread-pool:
core-size: 4
max-size: 8
queue-capacity: 1000 # 缓冲突发流量- 异步解耦:日志写入在独立线程池执行,零阻塞主业务流程
- 智能过滤:自动排除静态资源(
.js,.css)与监控端点(/actuator/**),减少 70%+ 无效日志 - 资源保护:限制请求体缓存大小(默认 1MB),防止大文件上传导致 OOM
5.3 合规与运维价值
- 安全事件回溯:快速定位异常操作(如批量删除、权限变更)
- 性能瓶颈分析:结合耗时数据识别慢接口
- 合规证据留存:满足 SOX、PCI DSS 等对“关键操作日志保留 ≥1 年”的要求
6. 安全体系核心优势总结
| 能力维度 | 技术亮点 | 业务价值 |
|---|---|---|
| 身份认证 | RS256 非对称签名 + 双 Token | 高安全性 + 无感续签体验 |
| 服务通信 | HMAC-SHA256 + 时间戳/Nonce | 轻量级、高吞吐、防重放 |
| 密钥管理 | 配置中心集成 + 动态加载 | 安全分发、便捷轮换 |
| 日志审计 | 异步采集 + 生命周期治理 | 合规就绪、运维提效 |
| 扩展性 | 模块化设计 + 开放 SPI | 支持对接 SIEM、SOC 等安全平台 |
7. 总结:让企业级安全成为默认选项
JavaFreeCloud 安全体系并非简单功能堆砌,而是基于纵深防御(Defense in Depth)思想构建的有机整体:
- 对外:通过标准化 JWT 协议,实现与前端、移动 App、第三方生态的无缝集成
- 对内:通过 HMAC 签名,建立微服务间的可信通信通道
- 对审计:通过全链路日志,构建“谁在何时做了什么”的完整证据链
开发者只需关注业务逻辑,安全细节由框架透明处理。这不仅大幅降低安全实施门槛,更确保安全策略在组织内一致、可靠、可持续地落地。
🔐 安全不是附加功能,而是架构基石 —— JavaFreeCloud 让企业级安全触手可及。
附录 A:安全配置参考(生产就绪)
JWT 配置 (jwt.yml)
jwt:
private.key: /opt/certs/app.key # 生产环境私钥路径
public.key: https://auth.example.com/public-key # 动态公钥(推荐)
private.key.password: "${JWT_KEY_PASS}" # 从环境变量读取
token:
token_name: Javafreeauthorization
expiration: 7200
refresh_expiration: 86400
security:
white_urls:
- /auth/token
- /auth/refresh_token
- /actuator/healthHMAC 配置(服务提供方)
# HMAC 签名认证配置
# 用于服务端验证客户端请求的合法性(基于对称密钥的 API 签名机制)
# 客户端需使用相同的 accessKey、secret 和 headerPrefix 生成签名头
hmac:
auth:
# 认证请求头前缀,客户端和服务端必须一致
# 例如:X-App- 表示头为 X-App-AccessKey, X-App-Signature 等
auth-header-prefix: X-App-HMAC 配置(服务调用方)
# HMAC 签名认证配置
# 用于服务端验证客户端请求的合法性(基于对称密钥的 API 签名机制)
# 客户端需使用相同的 accessKey、secret 和 headerPrefix 生成签名头
hmac:
auth:
# 访问密钥(Access Key),用于标识调用方身份
# 服务端可根据此 key 查找对应的 secret(支持多租户/多客户端场景)
# 示例值: AK_30628108_837043_19C7
access-key: your-access-key
# 签名密钥(Secret Key),必须严格保密!
# 用于生成和验证 HMAC-SHA256 签名,客户端与服务端必须一致
# ⚠️ 切勿提交到代码仓库!建议通过环境变量或配置中心注入
# 示例值: 2B3BF99C4618C76C53D96AAAD9CA7A388910810B225F2F373612C6CE1B3D5BA1
secret: your-secret-key
# HTTP 请求头前缀,所有认证相关头将以此开头
# 客户端会发送如:X-Custom-AccessKey, X-Custom-Timestamp, X-Custom-Nonce, X-Custom-Signature
# 默认值: X-App-
# 修改后需确保客户端与服务端保持一致
header-prefix: X-App-日志策略
# 操作日志配置
accesslog:
enabled: true # 是否开启日志存储 true or false
storage: jpa # 可选 jpa 或 elasticsearch
retention-minutes: 1440 # 日志保留多少分钟 默认 24 小时
cleanup-enabled: true
cleanup-cron: "0 0 1 * * ?" # 默认每天凌晨 1 点执行
cache-request-body: false # 是否保存请求体, 为了控制是否记录请求体 默认为 false
max-body-size: 1048576 # 超过这个值的字节数请求体,不缓存,默认 1M(1024*1024)
# 要排除的 URL 路径(Ant 风格,多个用逗号分隔)
exclude-paths: /actuator/**,/swagger-ui/**,/assets/**,/v3/api-docs/**,/webjars/**,/health
# 要排除的静态资源后缀(多个用逗号分隔)
exclude-suffixes: .js,.css,.png,.jpg,.jpeg,.gif,.ico,.woff,.woff2,.ttf,.svg,.eot,.map
# 日志保存异步线程池配置
thread-pool:
core-size: 4
max-size: 8
queue-capacity: 1000
keep-alive-seconds: 60
thread-name-prefix: AccessLog-Async-
await-termination-seconds: 30附录 B:遵循的安全标准
- 身份认证:OAuth 2.0 (RFC 6749), OpenID Connect Core 1.0
- 令牌格式:JWT (RFC 7519), JWA (RFC 7518)
- 加密算法:HMAC-SHA256 (FIPS 198-1), RSA-PKCS#1 v1.5
- 合规框架:GDPR Article 30, 等保 2.0 三级要求, PCI DSS v4.0
- 日志审计:ISO/IEC 27001:2022 A.8.16, NIST SP 800-92