微服务 API 网关:Spring Cloud Gateway 路由转发与鉴权(JWT)整合

Spring Cloud Gateway 路由转发与 JWT 鉴权整合指南

1. 核心依赖配置

pom.xml 添加必要依赖:

<dependencies>
    <!-- Gateway 核心依赖 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    
    <!-- JWT 处理库 -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.5</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

2. 路由配置(application.yml)
spring:
  cloud:
    gateway:
      routes:
        - id: auth-service
          uri: lb://AUTH-SERVICE  # 服务注册中心中的服务名
          predicates:
            - Path=/auth/**        # 匹配认证路径
          filters:
            - StripPrefix=1        # 移除路径前缀

        - id: user-service
          uri: lb://USER-SERVICE
          predicates:
            - Path=/api/users/**   # 用户服务路径
          filters:
            - JwtAuthFilter        # 自定义JWT过滤器

3. JWT 鉴权过滤器实现
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.Jwts;

@Component
public class JwtAuthFilter extends AbstractGatewayFilterFactory<JwtAuthFilter.Config> {

    private final String SECRET_KEY = "your-256-bit-secret"; // 实际应使用安全存储

    public JwtAuthFilter() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            // 1. 检查Authorization头
            String token = exchange.getRequest()
                .getHeaders()
                .getFirst("Authorization");

            if (token == null || !token.startsWith("Bearer ")) {
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }

            // 2. 提取并验证JWT
            try {
                String jwt = token.substring(7);
                Jwts.parserBuilder()
                    .setSigningKey(SECRET_KEY.getBytes())
                    .build()
                    .parseClaimsJws(jwt);
                
                // 3. 验证通过,继续路由
                return chain.filter(exchange);
                
            } catch (Exception ex) {
                // 4. 验证失败处理
                exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                return exchange.getResponse().setComplete();
            }
        };
    }

    public static class Config {}
}

4. 关键配置说明
  1. 路由规则

    • Path:定义URL匹配规则
    • StripPrefix:移除路径前缀(如 /auth/login 转发为 /login
    • lb://SERVICE-NAME:通过服务发现进行负载均衡
  2. JWT验证流程

    • 提取 Authorization 请求头
    • 验证 Bearer 令牌格式
    • 使用HS256算法验证签名
    • 异常处理:
      • 401 Unauthorized:缺少令牌
      • 403 Forbidden:无效令牌
5. 安全增强建议
  1. 密钥管理

    // 从配置中心读取密钥
    @Value("${jwt.secret}")
    private String secretKey;
    

  2. 令牌刷新机制

    • 在响应头中添加 X-Token-Refresh 提示客户端更新令牌
  3. 白名单配置

    // 在过滤器中添加免验证路径
    List<String> whitelist = Arrays.asList("/auth/login", "/public");
    if (whitelist.contains(path)) {
        return chain.filter(exchange);
    }
    

6. 测试流程
  1. 获取令牌

    curl -X POST http://gateway:8080/auth/login \
         -H "Content-Type: application/json" \
         -d '{"username":"user", "password":"pass"}'
    

  2. 访问受保护资源

    curl http://gateway:8080/api/users/profile \
         -H "Authorization: Bearer <JWT_TOKEN>"
    

7. 常见问题处理
  • 令牌过期:捕获 ExpiredJwtException 返回 401 状态码
  • 跨域问题:配置全局CORS
    spring:
      cloud:
        gateway:
          globalcors:
            cors-configurations:
              '[/**]':
                allowedOrigins: "*"
                allowedMethods: "*"
    

最佳实践:结合Spring Security OAuth2实现更复杂的授权场景(如Scope验证),网关层处理基础认证,微服务处理细粒度授权。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值