统一网关的登录流程总结

统一网关登录流程的面试要点,这是微服务架构中非常核心的高频考点。


🏗️ 整体架构图

复制代码
┌─────────────┐      ┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│   客户端     │      │  API Gateway │      │  认证中心    │      │  下游微服务  │
│ (Web/App)   │◄────►│   (统一网关)  │◄────►│ (Auth Server)│◄────►│ (业务服务)   │
└─────────────┘      └─────────────┘      └─────────────┘      └─────────────┘
                            │
                      ┌─────┴─────┐
                      │   Redis   │  ← Token黑名单/会话缓存
                      └───────────┘

🔐 核心登录流程(3种主流模式)

模式一:网关集中式认证(最常用)

流程步骤

  1. 用户登录 → 请求网关 /auth/login → 转发到认证中心
  2. 身份验证 → 认证中心校验用户名密码 → 生成 JWT Token(Access Token + Refresh Token)
  3. Token返回 → 网关返回 Token 给客户端
  4. 业务请求 → 客户端携带 Authorization: Bearer <token> 请求网关
  5. 统一鉴权 → 网关全局过滤器校验 JWT(签名、过期时间)
  6. 身份传递 → 网关将用户信息(UserID、Roles)写入请求头,转发给下游服务
  7. 业务处理 → 下游服务根据请求头中的用户信息进行权限判断和业务处理

核心代码(Spring Cloud Gateway):

java 复制代码
@Component
@Order(-1) // 最高优先级执行
public class JwtAuthenticationFilter implements GlobalFilter {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().value();
        
        // 1. 白名单放行(登录、注册、健康检查)
        if (isPublicPath(path)) {
            return chain.filter(exchange);
        }
        
        // 2. 提取 Token
        String token = extractToken(request);
        if (token == null) {
            return unauthorized(exchange, "缺少Token");
        }
        
        // 3. 校验 Token(签名、过期时间、黑名单)
        try {
            DecodedJWT jwt = JWTVerifier.verify(token);
            
            // 4. 将用户信息传递给下游服务
            ServerHttpRequest mutatedRequest = exchange.getRequest().mutate()
                .header("X-User-Id", jwt.getSubject())
                .header("X-User-Roles", jwt.getClaim("roles").asString())
                .header("X-User-Name", jwt.getClaim("username").asString())
                .build();
                
            return chain.filter(exchange.mutate().request(mutatedRequest).build());
            
        } catch (TokenExpiredException e) {
            return unauthorized(exchange, "Token已过期");
        } catch (JWTVerificationException e) {
            return unauthorized(exchange, "Token无效");
        }
    }
}

模式二:OAuth2 + JWT 授权码模式(第三方登录场景)

流程步骤

  1. 授权请求 → 客户端重定向到认证中心 /oauth2/authorize
  2. 用户登录 → 用户在认证中心完成登录并授权
  3. 授权码返回 → 认证中心返回 Authorization Code 给客户端
  4. 换取Token → 客户端携带 Code 请求网关 /oauth2/token
  5. 颁发Token → 网关返回 Access Token (JWT)+ Refresh Token(Opaque Token)
  6. 后续请求 → 同模式一,网关统一校验 JWT

Token 类型区别

Token 类型 格式 有效期 用途
Access Token JWT(自包含) 短(15-30分钟) 访问资源
Refresh Token Opaque(随机串) 长(7-30天) 刷新 Access Token
ID Token JWT 同 Access Token 包含用户基本信息(OIDC)

流程步骤

  1. 用户登录 → 网关验证凭证后创建 Session,存储在 Redis
  2. Cookie返回 → 网关设置 Set-Cookie: SESSION_ID=xxx 给浏览器
  3. 后续请求 → 浏览器自动携带 Cookie,网关从 Redis 查询 Session 获取用户信息
  4. 信息传递 → 网关将用户信息写入请求头转发

适用场景:传统服务端渲染 Web 应用,需要服务端控制会话状态


🛡️ 面试必问:网关统一认证 vs 服务自认证

维度 网关统一认证(推荐) 各服务自认证
安全性 统一安全策略,所有请求必须过网关 容易遗漏,策略不一致
性能 避免无效请求进入内网 重复解析 JWT,浪费资源
开发成本 服务无感知,专注业务 每个服务都要实现认证逻辑
灵活性 需要网关支持自定义规则 各服务可定制
运维复杂度 日志集中,便于审计 日志分散,难以追踪

面试金句"网关统一认证实现了认证边界的内移,在架构入口处建立单一可信边界,符合零信任架构的'永不信任,始终验证'原则"


🔄 Token 刷新机制(双 Token 策略)

为什么需要刷新?

  • Access Token 有效期短(15分钟),降低泄露风险
  • Refresh Token 有效期长(7天),但只用于换 Token,不直接访问资源

刷新流程

java 复制代码
// 伪代码:网关过滤器中实现 Token 自动刷新
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    String accessToken = extractToken(request);
    
    try {
        verifyToken(accessToken);
        return chain.filter(exchange);
    } catch (TokenExpiredException e) {
        // Token 过期,尝试用 Refresh Token 刷新
        String refreshToken = extractRefreshToken(request);
        
        if (refreshToken != null && validateRefreshToken(refreshToken)) {
            // 生成新 Access Token
            String newAccessToken = generateNewToken(refreshToken);
            
            // 返回新 Token(通过 Response Header 或 Body)
            exchange.getResponse().getHeaders().add("X-New-Token", newAccessToken);
            
            // 继续处理当前请求
            return chain.filter(exchange);
        } else {
            return unauthorized(exchange, "登录已过期,请重新登录");
        }
    }
}

🚨 安全加固要点(面试加分项)

1. Token 黑名单机制(主动登出)

java 复制代码
@Service
public class TokenBlacklistService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    // 登出时将 Token 加入黑名单(TTL 设为 Token 剩余有效期)
    public void addToBlacklist(String token, long expirationTime) {
        String jti = JWT.decode(token).getId(); // JWT ID
        long ttl = expirationTime - System.currentTimeMillis();
        redisTemplate.opsForValue().set("blacklist:" + jti, "1", ttl, TimeUnit.MILLISECONDS);
    }
    
    public boolean isBlacklisted(String token) {
        String jti = JWT.decode(token).getId();
        return redisTemplate.hasKey("blacklist:" + jti);
    }
}

2. 关键安全策略

策略 实现方式
HTTPS 强制 网关层强制 HSTS,拒绝 HTTP 请求
Token 存储 Access Token 存内存(Redux/Vuex),Refresh Token 存 HttpOnly Cookie
敏感操作二次认证 支付/修改密码等操作要求重新输入密码或短信验证
限流防刷 登录接口限流(如 5次/分钟),防止暴力破解
密钥轮换 定期更换 JWT 签名密钥,旧密钥保留一段时间用于验证旧 Token

3. 性能优化

java 复制代码
// JWT 解析结果缓存(Caffeine)
@Component
public class JwtCacheManager {
    private final Cache<String, DecodedJWT> cache = Caffeine.newBuilder()
        .expireAfterWrite(5, TimeUnit.MINUTES)
        .maximumSize(10000)
        .build();
        
    public DecodedJWT verifyWithCache(String token) {
        return cache.get(token, t -> JWTVerifier.verify(t));
    }
}

💼 面试高频问题 & 标准答案

Q1:网关鉴权失败,如何设计降级策略?

:熔断降级设计:

  • 认证中心不可用时,网关允许已缓存的公钥继续验证 Token(JWT 自包含特性)
  • 极端情况下可降级为只限流不鉴权,保证核心业务可用

Q2:如何实现"踢人下线"功能?

:三种方案:

  1. Token 黑名单:登出时将 JTI(Token ID)存入 Redis,网关校验时检查
  2. 修改密钥:强制所有 Token 失效(影响所有用户,慎用)
  3. Session 模式:直接删除 Redis 中的 Session 记录

Q3:网关如何处理下游服务的权限细化?

:网关负责粗粒度认证 (校验 Token 有效性),下游服务负责细粒度授权(判断用户是否有权操作某条数据)。网关传递用户角色/权限标识,服务内部做 RBAC/ABAC 判断 。

Q4:JWT 泄露了怎么办?

:短期泄露风险可控(Token 有效期短),长期:

  1. 立即将 Token 加入黑名单
  2. 轮换签名密钥
  3. 强制用户重新登录(清除 Refresh Token)

🎯 架构选型建议

场景 推荐方案 理由
纯内部微服务 网关 + JWT 无状态,性能好
涉及第三方登录 OAuth2 + JWT 标准协议,生态成熟
高安全要求金融场景 网关 + OAuth2 + mTLS 双向证书 + Token 双重验证
遗留系统改造 网关适配层 逐步迁移,兼容旧 Session

面试总结一句话"统一网关登录的核心是集中认证、分散授权------网关在入口处建立信任边界,通过无状态的 JWT 传递身份信息,既保证安全又实现服务间的解耦。"

相关推荐
cfm_29147 小时前
SpringBoot启动原理
java·spring boot·spring
漫随流水7 小时前
Java——springboot web案例
java·开发语言·spring boot
从此以后自律7 小时前
Java Object 类常用方法全讲解
java·开发语言
念何架构之路8 小时前
Docker 容器状态机 学习
java·学习·docker
你有我备注吗8 小时前
SQL学习之查询
java·sql·学习
xixi09248 小时前
JMeter5.6.3基础使用教程1
java·开发语言
带刺的坐椅8 小时前
用 Solon ReActAgent 落地发票识别与智能报销
java·llm·solon·react-agent
罗超驿9 小时前
15.Java异常处理:从束手无策到从容应对
java·开发语言
半夜修仙9 小时前
RabbitMQ的推模式和拉模式
java·分布式·中间件·rabbitmq·github·java-rabbitmq
掉鱼的猫9 小时前
用 Solon ReActAgent 落地发票识别与智能报销
java·llm·agent