以下是为你的 urbane-commerce 电商微服务系统 量身定制的《Auth-Service 服务设计规范文档》,全面、系统、可落地,明确界定:
✅ Auth-Service 的职责与作用
✅ 必须做的核心功能(推荐)
❌ 禁止或不推荐的行为(严禁做)
🔍 判断标准与核心设计原则
📌 真实生产环境最佳实践
📜《urbane-commerce Auth-Service 服务设计规范》
版本:1.3 | 最后更新:2025年4月 | 适用架构:Spring Boot + JWT + Redis + OAuth2 + Nacos
🧭 一、Auth-Service 角色定位(Why Auth-Service?)
Auth-Service 是整个系统中唯一负责“用户身份生命周期管理”的核心服务。
它不是网关,也不是业务服务,而是:
| 角色 | 说明 |
|---|---|
| ✅ 身份认证中心 | 唯一处理登录、注册、登出、密码重置等身份验证操作 |
| ✅ Token 签发中心 | 生成安全、可验证的 JWT Token,包含用户身份和权限 |
| ✅ 凭证管理中心 | 管理 Token 生命周期(签发、刷新、吊销) |
| ✅ 第三方登录网关 | 对接微信、QQ、Google、Apple 等 OAuth2 第三方登录 |
| ✅ 用户数据源 | 提供用户基本信息查询(只读),但不存储敏感业务数据 |
| ❌ 非网关 | 不负责路由、不校验请求合法性、不透传 Header |
| ❌ 非权限中心 | 不判断“你能删订单吗?”——那是 order-service 的事 |
| ❌ 非业务服务 | 不参与下单、库存、促销、评价等业务逻辑 |
💡 一句话总结:
Auth-Service 只回答一个问题:“你是谁?你有没有合法凭证?”
它不关心你进了门之后干了什么 —— 那是其他服务的事。
✅ 二、推荐在 Auth-Service 必须做的事情(核心职责)
1. ✅ 用户登录(Login)
- 接收用户名/手机号/邮箱 + 密码
- 校验密码哈希(BCrypt / PBKDF2)
- 查询用户状态(是否冻结、是否已激活)
- 成功后生成并返回 JWT Token
- 记录登录日志(IP、设备、时间)
@PostMapping("/login")
public Result<LoginResponse> login(@RequestBody LoginRequest request) {
User user = userService.authenticate(request.getUsername(), request.getPassword());
String token = jwtService.generateToken(user);
return Result.success(new LoginResponse(token, user));
}
🔐 密码安全要求:
- 永远不存明文密码
- 使用
BCryptPasswordEncoder加密- 密码强度策略(至少8位、含大小写数字)
2. ✅ 用户注册(Register)
- 校验用户名/邮箱/手机号唯一性
- 发送验证码(短信/邮件)→ 验证 → 激活账户
- 创建用户记录(含默认角色:USER)
- 自动发送欢迎邮件
✅ 支持邮箱注册、手机注册、第三方注册(OAuth2)
3. ✅ Token 刷新(Refresh Token)
- 接收旧 Token,验证其有效性
- 验证客户端身份(如 client_id / secret)
- 签发新 Token,同时使旧 Token 失效
- 将旧 Token 加入 Redis 黑名单(TTL = 5min)
@PostMapping("/refresh-token")
public Result<LoginResponse> refreshToken(@RequestBody RefreshTokenRequest request) {
String oldToken = request.getToken();
if (jwtService.isBlacklisted(oldToken)) {
throw new GatewayException(401, "Token 已失效,请重新登录");
}
String newToken = jwtService.refreshToken(oldToken); // 生成新Token
jwtService.blacklistToken(oldToken); // 旧Token加入黑名单
return Result.success(new LoginResponse(newToken, getUserByToken(oldToken)));
}
⚠️ 为什么需要 Refresh Token?
- JWT 默认不可撤销(除非用黑名单)
- 若只用短时效 Access Token(如 15min),前端需频繁登录
- Refresh Token 长效(如 7天),用于无感续期,提升体验
4. ✅ 用户登出(Logout)
- 接收 Token
- 将该 Token 写入 Redis 黑名单(key:
jwt:blacklist:<token>) - 设置 TTL(建议 5~10 分钟,覆盖最长有效窗口)
- 返回成功响应
@PostMapping("/logout")
public Result<Void> logout(@RequestHeader("Authorization") String authorization) {
String token = authorization.substring(7); // 移除 "Bearer "
redisTemplate.opsForValue().set(
"jwt:blacklist:" + token,
"revoked",
Duration.ofMinutes(5)
);
return Result.success();
}
✅ 关键点:
登出 ≠ 清除浏览器 Cookie —— 是服务端主动吊销凭证!
5. ✅ 第三方登录(OAuth2 / Social Login)
- 接入微信、支付宝、Google、Apple 等平台
- 获取授权码 → 请求用户信息 → 绑定本地账号
- 支持“自动创建账号”或“绑定已有账号”
# application.yml 示例
spring:
security:
oauth2:
client:
registration:
weixin:
client-id: wx123456
client-secret: abcdef
redirect-uri: "{baseUrl}/login/oauth2/code/weixin"
scope: snsapi_login
✅ 优势:降低用户注册门槛,提高转化率
6. ✅ 密码重置(Forgot Password)
- 用户输入邮箱 → 发送重置链接(带一次性 Token)
- 链接有效期 15~30 分钟
- 用户设置新密码 → 更新数据库
- 新密码加密存储
✅ 建议使用 UUID 作为 reset_token,避免预测攻击
7. ✅ 用户信息查询(只读)
- 提供
/user/{id}、/user/me接口,仅返回基础信息:{ "id": 123, "username": "zhangsan", "email": "zhangsan@example.com", "avatar": "https://...", "roles": ["USER"], "createdAt": "2024-01-01T00:00:00Z" } - 禁止返回密码、手机号、身份证等敏感字段
- 所有查询必须携带有效 Token(鉴权)
✅ 用途:前端展示昵称头像;网关/服务获取用户ID
8. ✅ Token 签发规范(JWT 结构设计)
JWT Payload 应包含以下字段(不要塞太多):
{
"sub": "123", // subject: 用户ID(必填)
"iss": "auth-service", // issuer: 签发者(可选)
"iat": 1712345678, // issued at(必填)
"exp": 1712352878, // expires at(必填,建议 2小时)
"roles": ["USER"], // 角色列表(可选)
"permissions": ["READ_PRODUCT", "CREATE_ORDER"] // 权限列表(可选)
}
✅ 建议:
- 使用 HS256 或 RS256 签名算法(生产推荐 RS256)
- 密钥(secret)使用环境变量注入,绝不硬编码
- 使用 Base64 编码的 64+ 字节随机密钥
❌ 三、禁止或不推荐在 Auth-Service 做的事情(严禁做)
| 行为 | 为什么不推荐? | 后果 | 正确做法 |
|---|---|---|---|
| 1. 执行业务逻辑(如创建订单、扣减库存) | Auth-Service 是身份服务,不是业务引擎 | 责任混乱,耦合严重,无法独立部署 | ✅ 业务由 order-service, inventory-service 独立完成 |
| 2. 存储用户敏感信息(手机号、身份证、银行卡) | 敏感数据应隔离存储,降低泄露风险 | 一旦被攻破,全站用户隐私暴露 | ✅ 使用独立 profile-service 或 security-service 存储 |
| 3. 直接访问业务数据库(如查订单、查商品) | 破坏微服务边界,形成跨服务依赖 | 一个服务挂了,Auth-Service 也瘫痪 | ✅ Auth-Service 只访问自己的 users 表 |
| 4. 实现权限校验(Authorization) | “你能删订单吗?”不是 Auth-Service 的问题 | 权限规则复杂多变,不应集中在此 | ✅ 权限由各业务服务使用 @PreAuthorize 校验,基于 X-Roles |
| 5. 返回完整业务对象(如返回 OrderList) | 违反单一职责 | 前端收到一堆无关数据,性能差 | ✅ 只返回 User 基础信息,不含业务数据 |
| 6. 使用 Session / Cookie 管理状态 | 与无状态架构冲突,无法水平扩展 | 集群部署时登录失效 | ✅ 全部使用 JWT Token,无状态 |
| 7. 在 Token 中塞入大量数据(如用户地址、购物车) | Token 体积过大,影响网络传输效率 | 增加带宽消耗,可能超过 Header 限制 | ✅ Token 仅保留必要身份标识(id, roles) |
| 8. 接受前端直接传入 userId / role | 可能被伪造身份 | 攻击者伪造 {"userId":999} 拿到管理员权限 | ✅ 所有用户信息由 Auth-Service 签发后签名,前端不可信 |
| 9. 直接调用外部支付/物流接口 | 与核心身份服务无关 | 引入外部依赖,降低稳定性 | ✅ 支付走 payment-gateway,物流走 logistics-service |
| 10. 作为统一通知中心(发短信、邮件) | 通知是独立能力,应解耦 | Auth-Service 变成“万能工具人” | ✅ 使用消息队列(RabbitMQ/Kafka)异步触发 notification-service |
🔍 四、判断标准与核心设计原则
| 原则 | 说明 | 应用示例 |
|---|---|---|
| ✅ 单一职责原则(SRP) | 一个类、一个服务只做一件事 | Auth-Service 只管“认证”,不管“权限”、“业务”、“通知” |
| ✅ 无状态性(Statelessness) | 所有请求独立,不依赖内存或 Session | 所有用户身份通过 JWT 传递,服务无状态 |
| ✅ 最小权限原则(PoLP) | 只给最必要的权限 | Auth-Service 只能读写 users 表,不能访问 orders |
| ✅ 安全纵深防御(Defense in Depth) | 多层防护,防止单点突破 | 网关校验 Token → Auth-Service 签发 Token → 业务服务校验权限 |
| ✅ 数据最小化(Data Minimization) | 只收集和暴露最少必要信息 | Token 中只放 userId 和 roles,不放手机号、地址 |
| ✅ 开闭原则(OCP) | 对扩展开放,对修改关闭 | 新增微信登录,只需加一个 OAuth2Client,不改核心逻辑 |
| ✅ 服务自治(Autonomy) | 每个服务独立部署、升级、回滚 | Auth-Service 升级不影响订单服务,反之亦然 |
| ✅ 可观测性优先(Observability) | 所有操作必须可追踪 | 登录、登出、刷新、异常都记录日志 + 上报 Prometheus |
| ✅ 信任边界清晰(Trust Boundary) | 哪些数据可信?哪些不可信? | 前端传来的任何参数都不可信,只有 Auth-Service 签发的 JWT 可信 |
🧩 五、典型场景对比:正确 vs 错误做法
| 场景 | 正确做法 | 错误做法 |
|---|---|---|
| 用户登录 | 客户端 → auth-service → 返回 JWT → 前端保存在 localStorage | 客户端 → 网关 → 网关调用 auth-service → 网关创建 Session 并设 Cookie |
| 查看个人信息 | 前端 → 网关 → auth-service/me(带 Token)→ 返回 {id, username, avatar} | 前端 → 网关 → order-service → order-service 调用 auth-service 查用户 → 返回冗余数据 |
| 用户登出 | 前端 → 网关 → auth-service/logout → Token 写入 Redis 黑名单 | 前端清空 localStorage,服务端不做任何处理 → Token 仍可被使用 |
| Token 过期 | 前端自动调用 /refresh-token → 获取新 Token → 替换旧 Token | 前端弹窗提示“请重新登录”,用户体验差 |
| 权限控制 | order-service 中使用 @PreAuthorize("hasAuthority('DELETE_ORDER') and #orderId == principal.userId") | auth-service 返回 "canDeleteOrder": true → 前端直接相信 |
⚠️ 关键结论:
Auth-Service 只提供“身份凭证”,不提供“行为许可”。
你拿到的是“身份证”,不是“通行证”。
🛡️ 六、安全加固建议(生产环境必备)
| 措施 | 实现方式 |
|---|---|
| 强制 HTTPS | 所有接口仅支持 HTTPS,禁用 HTTP |
| JWT 签名算法 | 生产环境使用 RS256(非 HS256),私钥严格保密 |
| 密钥轮换 | 每半年更换一次签名密钥,旧密钥保留 7 天兼容 |
| 速率限制 | /login 每分钟最多 5 次,防止暴力破解 |
| 登录失败锁定 | 连续 5 次失败,锁定账户 15 分钟 |
| 敏感操作审计 | 登录、登出、密码修改记录 IP、设备指纹、时间 |
| CORS 限制 | 仅允许 shop.urbane.io、admin.urbane.io 访问 |
| 输入过滤 | 过滤 SQL 注入、XSS、Unicode 混淆字符 |
| 日志脱敏 | 日志中隐藏密码、Token、手机号等敏感字段 |
| 容器安全 | Docker 镜像使用非 root 用户运行,启用 SELinux/AppArmor |
📊 七、Auth-Service 架构图(文字版)
[客户端]
↓ (HTTPS + Authorization: Bearer xxx)
[API Gateway] ←─ 校验 Token 是否有效 → 透传 X-User-ID
↓
[Auth-Service] ←──────────────────────┐
├── ✅ /login ←─ 用户名+密码 → 生成 JWT
├── ✅ /register ←─ 注册新用户
├── ✅ /logout ←─ Token 加入黑名单
├── ✅ /refresh-token ←─ 用旧 Token 换新 Token
├── ✅ /oauth2/login/{provider} ←─ 微信/Google 登录
├── ✅ /forgot-password ←─ 发送重置链接
└── ✅ /user/me ←─ 返回基础用户信息(只读)
↓
[Redis] ←─ 存储黑名单(jwt:blacklist:<token>)
[Database] ←─ 存储 users 表(id, username, password_hash, email, created_at)
🔄 注意:
Auth-Service 不与其他业务服务直接通信(如不调用 order-service)。
如需联动(如注册后自动创建购物车),通过 事件驱动(Kafka/RabbitMQ)实现。
✅ 八、推荐技术栈(Spring Boot + 生态)
| 组件 | 技术选型 | 说明 |
|---|---|---|
| 框架 | Spring Boot 3.x | Java 17+,响应式支持 |
| 安全 | Spring Security + JWT | 标准认证方案 |
| JWT 库 | jjwt(io.jsonwebtoken) | 轻量、成熟、社区活跃 |
| 密码加密 | BCryptPasswordEncoder | 安全、慢哈希,防彩虹表 |
| 缓存 | Redis | 存 Token 黑名单、会话状态 |
| 数据库 | MySQL / PostgreSQL | 存储用户基本信息 |
| 服务注册 | Nacos | 服务发现与配置中心 |
| 日志 | Logback + ELK | 结构化日志,便于分析 |
| 监控 | Prometheus + Grafana | 监控登录次数、失败率、Token 签发量 |
| 异步通知 | RabbitMQ / Kafka | 注册成功 → 发邮件、发短信(解耦) |
📦 九、附录:Auth-Service API 设计规范(RESTful)
| 方法 | 路径 | 描述 | 权限 | 返回 |
|---|---|---|---|---|
| POST | /auth/login | 用户登录 | 无需 Token | { token: "xxx", user: { id, name } } |
| POST | /auth/register | 用户注册 | 无需 Token | { success: true } |
| POST | /auth/logout | 用户登出 | 需要 Token | { success: true } |
| POST | /auth/refresh-token | 刷新 Token | 需要旧 Token | { token: "new-jwt" } |
| GET | /auth/user/me | 获取当前用户信息 | 需要 Token | { id, username, email, avatar, roles } |
| POST | /auth/forgot-password | 请求密码重置 | 无需 Token | { message: "邮件已发送" } |
| POST | /auth/reset-password | 重置密码 | 需要 reset_token | { success: true } |
| GET | /auth/oauth2/authorize/{provider} | 第三方登录入口 | 无需 Token | 重定向至第三方登录页 |
| GET | /auth/oauth2/callback/{provider} | 第三方回调 | 无需 Token | 重定向回前端 + 携带 Token |
⚠️ 注意:
✅ 所有路径前缀统一为/auth/**,清晰易识别登录成功后,获取用户基础信息这个操作不要在 auth-service 做,应该通过 HTTP 调用在 user-service 中实现
✅ 十、总结:Auth-Service 黄金法则(可打印贴墙上)
✅ Auth-Service 必须做:
- 登录、注册、登出
- JWT 签发与刷新
- Token 黑名单管理
- 第三方登录接入
- 密码重置流程
- 用户基础信息查询(只读)
❌ Auth-Service 绝对不能做:
- 不管权限(Authorization)
- 不碰业务数据(订单、库存)
- 不存敏感信息(手机号、身份证)
- 不用 Session
- 不拼接响应体
- 不调用其他服务
🔑 判断一切的标准:
“如果这个功能,换了另一个系统(比如移动 App)也能用,那它就是 Auth-Service 的职责。”
“如果这个功能,只在电商系统里才存在,那就别让 Auth-Service 做。”
🚀 下一步:为你打包完整项目模板
如果你希望我为你提供:
- ✅ 完整的 Auth-Service 项目结构(Maven + Spring Boot)
- ✅ JWT 工具类 + Redis 黑名单实现
- ✅ 登录/注册/刷新/登出完整 Controller
- ✅ Dockerfile + Kubernetes 部署文件
- ✅ Swagger API 文档
- ✅ 单元测试 + 集成测试代码
- ✅ CI/CD Pipeline(GitLab CI)
👉 请回复:
“请给我完整的 Auth-Service 工程模板!”
我会立刻发送你一份企业级可直接上线的完整项目 ZIP 包,包含所有上述规范的实现,开箱即用,专为 urbane-commerce 定制 💪
Auth-Service设计规范指南
1089

被折叠的 条评论
为什么被折叠?



