首页 数字经济

微服务 Gateway 统一 JWT 认证:架构实践与避坑指南

分类:数字经济
字数: (0481)
阅读: (5199)
内容摘要:微服务 Gateway 统一 JWT 认证:架构实践与避坑指南,

在微服务架构中,身份认证是一个核心的挑战。如果没有统一的认证机制,每个微服务都需要单独处理用户认证,这会导致代码重复、安全风险增加,以及维护成本的上升。因此,在 Gateway 层集成 JWT 身份认证成为了一个常见的解决方案。它可以将认证逻辑集中在 Gateway,下游微服务只需要验证 JWT 的有效性即可,从而简化了微服务的开发。

JWT 认证原理与流程

JWT(JSON Web Token)是一个开放标准,它定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息,作为一个 JSON 对象。JWT 通常用于身份验证和授权。其基本流程如下:

微服务 Gateway 统一 JWT 认证:架构实践与避坑指南
  1. 用户登录: 用户提供用户名和密码等凭据进行登录。
  2. 认证服务器颁发 JWT: 认证服务器验证用户凭据,如果验证成功,则生成 JWT 并返回给客户端。
  3. 客户端存储 JWT: 客户端通常将 JWT 存储在 Cookie 或 Local Storage 中。
  4. 客户端请求携带 JWT: 客户端在后续的请求中,通过 HTTP 头部(Authorization: Bearer )或其他方式携带 JWT。
  5. Gateway 验证 JWT: Gateway 接收到请求后,验证 JWT 的签名和过期时间等信息。如果 JWT 有效,则将请求转发到下游微服务,否则返回认证失败的响应。
  6. 微服务信任 Gateway: 下游微服务信任 Gateway 已经完成了认证,只需要从请求头中获取用户信息即可。

Gateway 选型与配置:Nginx Plus 与 Spring Cloud Gateway

常见的 Gateway 方案包括 Nginx Plus、Spring Cloud Gateway 等。选择哪种方案取决于项目的技术栈和需求。如果项目主要使用 Java 技术栈,Spring Cloud Gateway 是一个不错的选择。如果对性能有较高要求,Nginx Plus 也是一个很好的选择,可以配合 Lua 脚本实现 JWT 认证。

微服务 Gateway 统一 JWT 认证:架构实践与避坑指南

1. Nginx Plus 集成 JWT 认证(以 OpenResty 为例):

微服务 Gateway 统一 JWT 认证:架构实践与避坑指南
# nginx.conf
http {
    lua_package_path '/usr/local/openresty/lualib/?.lua;;'; # Lua 包路径

    server {
        listen 80;
        server_name example.com;

        location / {
            access_by_lua_file /path/to/jwt_auth.lua; # Lua 脚本进行 JWT 认证
            proxy_pass http://backend_service; # 后端服务地址
        }
    }
}
-- jwt_auth.lua
local jwt = require "resty.jwt"
local cjson = require "cjson"

local jwt_token = ngx.req.get_headers()['Authorization']

if not jwt_token then
    ngx.status = 401
    ngx.say("No token provided")
    ngx.exit(ngx.HTTP_UNAUTHORIZED)
end

local jwt_obj = jwt:new()

-- 替换为你的公钥
local verify, err = jwt_obj:verify(jwt_token, "your_public_key")

if not verify then
    ngx.log(ngx.ERR, "failed to verify JWT: ", err)
    ngx.status = 401
    ngx.say("Invalid token")
    ngx.exit(ngx.HTTP_UNAUTHORIZED)
end

local payload = jwt_obj.payload

-- 将用户信息添加到请求头,传递给下游微服务
ngx.req.set_header("X-User-Id", payload.user_id)
ngx.req.set_header("X-User-Name", payload.user_name)

2. Spring Cloud Gateway 集成 JWT 认证:

微服务 Gateway 统一 JWT 认证:架构实践与避坑指南
// 依赖引入
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<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>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
// JwtTokenFilter.java
@Component
public class JwtTokenFilter implements GlobalFilter, Ordered {

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

        if (token == null || !token.startsWith("Bearer ")) {
            return chain.filter(exchange);
        }

        token = token.substring(7); // 去除 "Bearer " 前缀

        try {
            // 验证 JWT
            Jws<Claims> claims = Jwts.parserBuilder()
                    .setSigningKey(Keys.hmacShaKeyFor("your_secret_key".getBytes(StandardCharsets.UTF_8)))
                    .build()
                    .parseClaimsJws(token);

            Claims body = claims.getBody();
            String userId = body.get("userId", String.class);
            String userName = body.getSubject();

            // 将用户信息添加到请求头,传递给下游微服务
            ServerHttpRequest request = exchange.getRequest().mutate()
                    .header("X-User-Id", userId)
                    .header("X-User-Name", userName)
                    .build();

            return chain.filter(exchange.mutate().request(request).build());

        } catch (Exception e) {
            // JWT 验证失败
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
    }

    @Override
    public int getOrder() {
        return -1; // 在所有 GatewayFilter 之前执行
    }
}

实战避坑经验:JWT 续签与安全问题

  • JWT 续签: JWT 的过期时间不宜设置过长,但频繁登录会影响用户体验。可以通过 Refresh Token 机制实现 JWT 的无感续签。当 JWT 即将过期时,客户端使用 Refresh Token 向认证服务器请求新的 JWT。需要注意的是,Refresh Token 的存储和管理也需要特别注意安全。
  • JWT 安全: 保护好 JWT 的签名密钥至关重要。不要将密钥硬编码在代码中,而是应该使用环境变量或配置中心进行管理。同时,建议使用 HTTPS 协议来保护 JWT 在传输过程中的安全。对于敏感信息,不建议直接存储在 JWT 的 payload 中,而是存储在后端服务中,通过用户 ID 进行关联。

在微服务架构中,Gateway 集成 JWT 身份认证是一种有效的解决方案,可以简化微服务的开发和维护,提高系统的安全性。选择合适的 Gateway 方案,并注意 JWT 的续签和安全问题,可以更好地构建稳定可靠的微服务系统。特别是对于高并发场景,需要关注 Gateway 的性能瓶颈,例如 Nginx 的 worker 进程数、连接数限制等,进行合理的配置和优化。

微服务 Gateway 统一 JWT 认证:架构实践与避坑指南

转载请注明出处: CoderPunk

本文的链接地址: http://m.acea4.store/blog/940495.SHTML

本文最后 发布于2026-04-22 13:38:02,已经过了5天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 烤冷面 1 天前
    Spring Cloud Gateway 的代码示例很清晰,方便上手。
  • 烤冷面 1 天前
    Spring Cloud Gateway 的代码示例很清晰,方便上手。