当前位置: 首页 > news >正文

3、用户认证与鉴权应该放在哪里进行?

这是一个非常关键、且在真实企业级 Spring Cloud 微服务电商项目中必须精准设计的核心问题:

用户认证(Authentication)与鉴权(Authorization)应该放在哪里?推荐在哪里处理?实际项目中是怎么做的?


✅ 一句话结论(先看结果)

在 Spring Cloud 微服务电商系统中:

🔹 认证(Authentication) → 放在 API 网关(Gateway)或独立的 Auth Service
🔹 鉴权(Authorization) → 放在 每个业务微服务内部
🔹 最佳实践组合
👉 网关做“初步认证 + JWT 校验”
👉 各服务做“细粒度权限校验”
👉 统一使用 OAuth2 / JWT + RBAC 权限模型
👉 所有请求携带 Token,不依赖 Session


🧩 一、基本概念区分

概念含义举个例子
Authentication(认证)“你是谁?”
验证身份是否合法
用户输入账号密码 → 系统确认是张三
Authorization(鉴权)“你能做什么?”
验证权限是否足够
张三能查看订单,但不能删除商品

💡 认证是“进门”,鉴权是“进哪个房间”。


🏗️ 二、推荐架构设计(Spring Cloud 微服务电商标准方案)

✅ 推荐架构图(文字版)

[客户端] ↓ (携带 JWT Token)
[API Gateway - urbane-commerce-gateway]↓ 验证 Token 是否有效、过期、签名↓ 提取用户ID、角色、权限 → 注入到 Request Header (如 X-User-ID, X-Permissions)↓ 放行给后端服务
[product-service] → 检查:当前用户是否有 "READ_PRODUCT" 权限?
[order-service]   → 检查:当前用户是否是该订单的所有者?
[cart-service]    → 检查:是否为登录用户操作自己的购物车?
[auth-service]    ← 独立服务:负责登录、刷新Token、密码管理

核心原则:网关做“守门人”,服务做“裁判员”


📍 三、具体组件职责划分(实战落地)

组件职责技术实现是否推荐
API Gateway(网关)认证中心
- 验证 JWT 签名
- 检查 Token 是否过期
- 解析 payload 中的 user_id, roles
- 将用户信息注入 HTTP Header(如 X-User-ID, X-Roles
- 拦截未授权访问(401)
Spring Cloud Gateway + JwtDecoder + Filter✅✅✅ 强烈推荐
Auth Service(独立认证服务)唯一登录入口
- 处理 /login/refresh-token
- 校验用户名密码
- 生成 JWT(含用户 ID、角色、权限)
- 可对接 LDAP/SSO/第三方登录(微信、Google)
Spring Boot + Spring Security + JWT + Redis(存黑名单)✅✅✅ 强烈推荐
业务微服务(如 order-service)鉴权中心
- 从 Header 获取用户信息
- 校验当前操作是否拥有对应权限(如:canDeleteOrder
- 检查“所有权”(如:你只能操作自己的订单)
- 使用 @PreAuthorize("hasAuthority('DELETE_ORDER')")
Spring Security + 方法级注解 / 自定义拦截器✅✅✅ 必须做
数据库 / 权限表存储权限关系users, roles, permissions, user_roles, role_permissions✅✅✅ 必须有
Redis缓存 Token 黑名单(退出登录)、限流存放已注销的 JWT token(key: jwt:blacklist:xxx✅✅ 推荐

⚠️ 不推荐:把所有鉴权逻辑都丢给网关 —— 它无法知道“这个订单是不是你的”


🔍 四、为什么这样设计?—— 实战中的思考

问题为什么不放在网关全管?为什么不只在服务里做?
Q1:网关怎么知道“这个订单属于当前用户”?❌ 网关不知道业务语义!它只知道“Token 有效”。订单归属是业务逻辑,只有 order-service 懂。✅ 服务自己查 DB:SELECT * FROM orders WHERE user_id = ? AND id = ?
Q2:用户退出登录,如何立即失效 Token?✅ 网关可检查 Redis 黑名单(轻量)✅ 服务无需感知,只需信任 Header
Q3:权限变更(如管理员提升)如何生效?❌ 如果只靠 JWT,需等过期才更新✅ 服务可缓存权限,结合 Redis 刷新(TTL 5min)
Q4:性能影响?✅ 网关校验 JWT 是内存计算,极快✅ 服务鉴权用缓存,不会每次都查库
Q5:微服务独立部署?✅ 每个服务都能独立运行,只要传 Header 即可✅ 不依赖网关存在

结论:网关是“安检口”,服务是“包间保安”
—— 两者分工明确,缺一不可。


🛠️ 五、真实项目中的典型实现(大厂/中型团队做法)

✅ 1. 认证流程(登录)

sequenceDiagramparticipant Clientparticipant Gatewayparticipant Auth-Serviceparticipant DBClient->>Auth-Service: POST /auth/login {username, password}Auth-Service->>DB: 查询用户密码,比对DB-->>Auth-Service: 返回用户信息Auth-Service->>Auth-Service: 生成 JWT(含 user_id, roles, permissions)Auth-Service->>Client: 返回 {token: "eyJ...", expires_in: 3600}

✅ 2. 请求流程(带 Token 访问订单)

sequenceDiagramparticipant Clientparticipant Gatewayparticipant Order-Serviceparticipant RedisClient->>Gateway: GET /orders/123 Authorization: Bearer <JWT>Gateway->>Gateway: 解析 JWT,验证签名 & 过期时间Gateway->>Redis: 检查 token 是否在黑名单(退出登录)Gateway->>Order-Service: Forward 请求 + Header: X-User-ID=5, X-Roles=admin,userOrder-Service->>Order-Service: @PreAuthorize("hasAuthority('READ_ORDER') and #orderId == principal.userId")Order-Service->>DB: SELECT * FROM orders WHERE id=123 AND user_id=5DB-->>Order-Service: 返回订单Order-Service-->>Gateway: 200 OKGateway-->>Client: 200 OK

✅ 3. 权限模型(RBAC + 资源所有者)

表结构示例
users(id, username, password_hash)
roles(id, name: ‘USER’, ‘ADMIN’, ‘MODERATOR’)
permissions(id, code: ‘READ_PRODUCT’, ‘DELETE_ORDER’, ‘UPDATE_STOCK’)
user_roles(user_id, role_id)
role_permissions(role_id, permission_id)

🔐 在 order-service 中:

@PreAuthorize("hasAuthority('READ_ORDER') and #orderId == authentication.principal.userId")
@GetMapping("/{orderId}")
public Order getOrder(@PathVariable Long orderId) {return orderService.findById(orderId);
}

✅ 这样既保证了角色权限,也保证了数据所有权


💡 六、进阶优化建议(真实项目必备)

优化点实现方式效果
JWT 缓存权限将用户权限缓存到 Redis(Key: user:perms:5),Token 中只存 userId减少每次鉴权查库,支持动态权限更新
权限刷新机制当管理员修改用户权限时,清除 Redis 中该用户的权限缓存实时生效,无需重新登录
跨服务权限调用使用 Feign + 拦截器传递 X-User-IDX-Permissions内部服务调用也能继承身份
日志追踪在网关和所有服务中记录 X-Request-ID + X-User-ID便于审计和排查问题
OpenTelemetry 集成为认证/鉴权链路打埋点监控鉴权耗时、失败率
多租户支持在 JWT 中增加 tenant_id,所有查询加 WHERE tenant_id = ?支持 SaaS 化

🚫 七、常见错误做法(避坑指南)

错误做法问题
所有鉴权都在网关做无法控制“谁可以删自己的订单”,只能控制“能不能访问订单接口”→ 安全漏洞
使用 Session + Cookie微服务无状态架构被破坏,无法横向扩展,集群部署困难
JWT 中塞太多数据Token 过大,网络传输成本高,可能超过 header 限制
不校验 Token 过期导致长期有效的 Token 泄露后风险极高
不做黑白名单用户登出后仍可继续使用旧 Token
服务之间直接调用不传身份A 服务调 B 服务时冒充用户 → 权限绕过

📦 八、代码结构建议(Spring Boot 项目结构)

urbane-commerce/
├── services/
│   ├── auth-service/             ← 唯一认证中心
│   │   ├── controller/AuthController.java
│   │   ├── service/JwtService.java
│   │   └── config/SecurityConfig.java
│   │
│   ├── order-service/            ← 业务服务
│   │   ├── controller/OrderController.java
│   │   ├── service/OrderService.java
│   │   ├── config/WebSecurityConfig.java   ← 开启方法级权限
│   │   └── aspect/PermissionAspect.java    ← 自定义权限切面(可选)
│   │
│   └── urbane-commerce-gateway/  ← API 网关
│       ├── filter/JwtAuthenticationFilter.java  ← 核心!校验并注入Header
│       ├── config/GatewayConfig.java
│       └── security/JwtUtil.java
│
└── commons/└── urbane-commons/└── model/UserContext.java          ← 存储当前用户信息(ThreadLocal)└── interceptor/UserInterceptor.java ← 从Header提取用户信息到 ThreadLocal

💡 UserContext 工具类(线程安全):

public class UserContext {private static final ThreadLocal<UserInfo> context = new ThreadLocal<>();public static void setUser(UserInfo user) { context.set(user); }public static UserInfo getUser() { return context.get(); }public static void clear() { context.remove(); }
}

在网关过滤器中设置,在业务服务中读取:

// 在 OrderController 中
UserInfo currentUser = UserContext.getUser();
if (!currentUser.getId().equals(order.getUserId())) {throw new UnauthorizedException("你无权访问此订单");
}

✅ 总结:终极答案(面试/汇报可用)

在真实的 Spring Cloud 微服务电商项目中:

  1. 认证(Authentication)由独立的 auth-service 处理,网关负责校验 JWT 是否合法;
  2. 鉴权(Authorization)由每个业务服务自行完成,基于角色 + 数据所有权双重校验;
  3. 所有服务通过 HTTP Header(如 X-User-ID)传递用户身份,无状态、可扩展;
  4. 使用 JWT + RBAC + Redis 黑名单 + 方法级注解(@PreAuthorize)构建完整安全体系;
  5. 严禁使用 Session,禁止将业务权限判断交给网关。

🔒 安全底线:永远不要相信客户端传来的任何信息,即使它带着 Token。


如果你需要我为你提供一份 完整的可运行 Demo 项目结构(含 GitHub 风格代码模板),包括:

  • auth-service 登录接口
  • gateway 的 JWT 过滤器
  • order-service@PreAuthorize 示例
  • UserContext 工具类

我可以为你打包成一个 ZIP 或 Git 仓库结构,直接复制到你的项目中使用 👇

只需告诉我:“请给我完整代码模板!” 我立刻发你 🚀

http://www.dtcms.com/a/406536.html

相关文章:

  • iOS 混淆与 App Store 审核兼容性 避免被拒的策略与实战流程(iOS 混淆、ipa 加固、上架合规)
  • 界面设计最好的网站举例网站联盟
  • 无服务器 AI 应用:Lambda + SageMaker Endpoint 实时预测服务(技术深度版)
  • 装修公司 网站模板深圳工作服制作
  • React学习教程,从入门到精通,React 单元测试:语法知识点及使用方法详解(30)
  • Wouter 和 React Router的区别
  • 关于如何让 Vosk 正确识别中文音频,核心是 使用 Vosk 中文模型 + 确保中文音频格式符合要求
  • MySQL和PostgreSQL的数据库主键索引都是B+树吗?
  • VUE、jquery、React、Ant Design、element ui、bootstrap 前端框架的 功能总结,示例演示、使用场景介绍、完整对比总结
  • PDF格式转换、PDF编辑全功能解锁,功能图文教程
  • C++项目:仿muduo库高并发服务器
  • 建设网站业务不好做请问那个网站做推广好点
  • Pytest+requests进行接口自动化测试6.0(Jenkins)
  • elasticsearch安装插件
  • html5移动网站开发html5新增标签
  • 前端工程化基础知识
  • 【C#】以 BlockingCollection 为核心的多相机 YOLO 检测任务处理框架
  • (11)ASP.NET Core2.2 中的配置一(Configuration)
  • 在 C# .NETCore 中使用 MongoDB(第 1 部分):驱动程序基础知识和插入文档
  • php做图片交互网站代码网站下要加个备案号 怎么做
  • 巴中商城网站建设wordpress 图书主题
  • 一键预约上门服务:到家洗车小程序的便捷功能与场景化体验
  • 第 3 篇:让图形动起来 - WebGL 2D 变换
  • 寝室快修|基于SprinBoot+vue的贵工程寝室快修小程序(源码+数据库+文档)
  • 青秀网站建设网站海外推广平台
  • 前端基础:从0到1实现简单网页效果(二)
  • 基于LazyLLM搭建AI创意文案生成器(多场景文案自动生成)
  • 数据链路层:网络通信的基础与桥梁
  • Keepalived两个集群实验
  • vs网站开发表格大小设置网站建设要注意一些什么