网关设计
网关是无状态的,可以任意水平扩容;用户状态只存在 user-center 的库和 Redis 里。 一旦网关开始查业务库判断「能不能访问这条订单」,它就退化成了最大的那个单体。
Filter 顺序与踩坑
对应 AuthGlobalFilter 的 order = -100,必须早于
StripPrefix 等路由级过滤器。
最容易踩的坑:限流白名单必须匹配 原始路径
(如 /api/auth/register),而不是 StripPrefix 之后的
/register。配错前缀等于鉴权失效。
Nacos 路由配置示例
在 Nacos 建 data-id 为 gateway-routes.yaml
(已在 bootstrap.yml 里配成 shared-config,改动可热刷新):
spring:
cloud:
gateway:
routes:
- id: user-center
uri: lb://user-center
predicates:
- Path=/api/auth/**,/api/users/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
key-resolver: '#{@principalKeyResolver}'
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1
application.yml 里的 routes 只是本地兜底。生产建议把
spring.cloud.gateway.discovery.locator.enabled 关掉、走显式路由——
隐式路由会不小心把 actuator、内部接口一起暴露到公网。
刻意留下的 TODO
这些是有意留白,不是漏做:
AuthController.login里的风控钩子:设备指纹、异地登录、连续失败锁定。UserDirectory接口需要接真实持久层(MyBatis / JPA 均可)。- 注册后的
UserRegisteredEvent建议接到 MQ,驱动积分、营销、风控异步消费。
判断权限在哪一层
| 判定 | 在哪一层做 |
|---|---|
| 令牌真假、是否过期、是否被吊销 | 网关 |
| 接口是否需要登录 | 网关白名单 |
| 这个用户能不能看这条数据(行级) | 业务服务 |
| 按钮 / 菜单级权限 | 业务服务,依据网关注入的 X-User-Roles |
| 团队负责人的继承权限 | 业务服务,按 X-User-Id 取 team_members,
再沿 teams.parent_id 递归取整棵子树 |