统一网关的登录流程总结

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


🏗️ 整体架构图

复制代码
┌─────────────┐      ┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│   客户端     │      │  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 传递身份信息,既保证安全又实现服务间的解耦。"

相关推荐
闻哥1 小时前
从测试坏味道到优雅实践:打造高质量单元测试
java·面试·单元测试·log4j·springboot
计算机程序设计小李同学2 小时前
基于 Spring Boot + Vue 的龙虾专营店管理系统的设计与实现
java·spring boot·后端·spring·vue
LiZhen7982 小时前
SpringBoot 实现动态切换数据源
java·spring boot·mybatis
周航宇JoeZhou2 小时前
JB2-7-HTML
java·前端·容器·html·h5·标签·表单
JZC_xiaozhong2 小时前
多系统权限标准不统一?企业如何实现跨平台统一权限管控
java·大数据·微服务·数据集成与应用集成·iam系统·权限治理·统一权限管理
爬山算法3 小时前
Hibernate(85)如何在持续集成/持续部署(CI/CD)中使用Hibernate?
java·ci/cd·hibernate
菜鸟233号3 小时前
力扣647 回文子串 java实现
java·数据结构·leetcode·动态规划
qq_12498707534 小时前
基于Java Web的城市花园小区维修管理系统的设计与实现(源码+论文+部署+安装)
java·开发语言·前端·spring boot·spring·毕业设计·计算机毕业设计
h7ml4 小时前
查券返利机器人的OCR识别集成:Java Tesseract+OpenCV优化图片验证码的自动解析方案
java·机器人·ocr