🛡️Spring Cloud Gateway 就是个“反向代理”?那你可太小看它了!

举报
bug菌 发表于 2025/06/05 17:25:53 2025/06/05
【摘要】 🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

前序

🤔“网关不就是转发一下请求?写几个路由规则不就搞定了?鉴权嘛,后端来做呗,Gateway 就别参与了。”

✋先慢着!如果你也这么想,那我劝你……赶紧收藏这篇文章!

因为在一个成熟且安全的微服务系统里,Spring Cloud Gateway 不仅是流量入口,更是第一道安全防线,负责识别用户、鉴权验证、访问控制、异常拦截……就差没给请求洗个澡了。

🌉前言:微服务不设防,迟早出大事!

想象一下你家的大门永远敞开着,谁想进就进,连个门卫都没有——微服务架构如果没有一个强有力的网关控制层,那基本就等于给黑客“发请帖”。

而 Spring Cloud Gateway,就是我们构建安全网关策略的理想“武器”🛠️。

🔍Spring Cloud Gateway 是什么?

Spring Cloud Gateway 是 Spring 官方推出的新一代网关解决方案,它基于 WebFlux,天然支持响应式,性能轻巧,扩展能力极强。

🚦它的核心能力包括:

  • 🌐 路由转发(Path/Host/Query 等条件)
  • 🧱 过滤器链(前置、后置、全局等)
  • 🔐 鉴权与权限控制
  • 🔁 熔断/限流/重试/缓存
  • 📈 日志跟踪与监控整合(Zipkin, Sleuth)

🧭一张图看懂 Gateway 安全流程

[外部客户端]
      |+-----------------------+
|   Spring Cloud Gateway|<-------------------+
|   - 鉴权过滤器         |                    |
|   - 路由转发           |                    |
+-----------------------+                    |
      |                                     ||
[认证服务 - JWT颁发] <----  OAuth2/OpenID Connect
      |[各类微服务 - 有状态业务]

JWT:用户登录后生成的令牌,携带用户信息(无状态)。
OAuth2:更适合授权第三方访问,比如“用微信登录”。

🧑‍💻实战:让 Gateway 成为“带刀护卫”,守好系统大门!

1️⃣ 创建 Gateway 服务

添加依赖:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.1</version>
</dependency>

配置路由:

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/user/**
          filters:
            - StripPrefix=1

2️⃣ 编写全局鉴权过滤器 ✋

我们要自定义一个全局过滤器来拦截所有请求,验证 JWT。

@Component
public class JwtAuthFilter implements GlobalFilter, Ordered {

    private static final String AUTH_HEADER = "Authorization";
    private static final String BEARER = "Bearer ";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = resolveToken(exchange.getRequest().getHeaders());

        if (token == null || !validateToken(token)) {
            return unauthorized(exchange);
        }

        // 🧠 解析用户信息,可通过Header传给下游服务
        Claims claims = getClaims(token);
        exchange.getRequest().mutate()
                .header("X-User-Id", claims.getSubject())
                .build();

        return chain.filter(exchange);
    }

    private String resolveToken(HttpHeaders headers) {
        String bearerToken = headers.getFirst(AUTH_HEADER);
        return (bearerToken != null && bearerToken.startsWith(BEARER)) ?
                bearerToken.substring(BEARER.length()) : null;
    }

    private boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey("your-secret-key").parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private Claims getClaims(String token) {
        return Jwts.parser()
                   .setSigningKey("your-secret-key")
                   .parseClaimsJws(token)
                   .getBody();
    }

    private Mono<Void> unauthorized(ServerWebExchange exchange) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        return response.setComplete();
    }

    @Override
    public int getOrder() {
        return -1; // 高优先级
    }
}

✍️说明:这里我们简单地从请求头中解析 JWT,如果 token 校验失败,则返回 401。

3️⃣ 用户服务如何生成 JWT?

public String generateToken(String userId) {
    return Jwts.builder()
            .setSubject(userId)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 86400000)) // 1天
            .signWith(SignatureAlgorithm.HS256, "your-secret-key")
            .compact();
}

🔐进阶:OAuth2 + Spring Authorization Server 实战集成(略)

OAuth2 是企业级系统更推荐的做法,可以通过以下方式集成:

  • 使用 spring-authorization-server 创建认证中心
  • Gateway 配置 AuthorizationFilter
  • 启用 JWT token 颁发与校验
  • 支持 OAuth2 Scopes 与资源角色映射

想看完整 OAuth2 架构 + Spring Authorization Server 实战文章?你就说一句,马上安排!🔥

🔁常见安全增强:限流、黑名单、加密传输

功能 实现方式
IP限流 RequestRateLimiter 过滤器 + Redis
黑白名单 配置自定义 Predicate
HTTPS 强制 Nginx 或 Gateway 配置 SSL
请求签名校验 自定义签名过滤器(防重放)

🧩如果系统要对接微信/钉钉登录?

推荐使用 OAuth2 的 openid-connect 模式:

spring:
  security:
    oauth2:
      client:
        registration:
          wechat:
            client-id: xxxxx
            client-secret: xxxxx
            provider: wechat

⚠️ 外部登录回调不直接进微服务,统一走 Gateway + 登录中心处理!

🤔为什么要“在网关层做鉴权”?

集中式安全模型!

  • 🛡️ 不重复造轮子,每个微服务不用各自验证 token
  • 📉 降低服务负载,先拦截非法请求
  • 🔗 统一用户上下文传递(X-User-Id、X-Role 等)
  • 🔍 配合日志系统,实现完整链路追踪

🧠常见误区与建议

常见做法 是否推荐 原因
每个服务都校验 JWT 增加代码复杂度,容易重复出错
网关转发时暴露原始 Header 敏感信息风险
网关不加日志追踪 调试极其困难
JWT 不设置过期时间 安全性隐患
Token 缓存在网关 ✅/❌ 视场景而定,建议做缓存黑名单机制

✅总结:安全不是“附加项”,而是“设计原点”

Spring Cloud Gateway 是一把利刃,但用不好,就可能变成隐患。

只有当我们理解了网关不仅仅是“转发器”,而是“安全代理 + 策略控制器”,才真正用好这个微服务体系的核心“哨兵”。

❓尾声反问:你的网关,是“通行证”,还是“防火墙”?

朋友,千万别让 Gateway 成为一个“摆设”。
用好 JWT、OAuth2、过滤器、限流、日志链路追踪,让它真正变成系统的第一道护城河。你安全了,才有资本谈扩展、谈弹性、谈创新!

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」专栏(全网一个名),bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

  最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

  同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

✨️ Who am I?

我是bug菌(全网一个名),CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主/价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。