Spring Cloud Gateway 实现登录校验:构建统一认证入口

发布于:2025-08-05 ⋅ 阅读:(18) ⋅ 点赞:(0)

Spring Cloud Gateway 实现登录校验:构建统一认证入口

一、为什么需要在网关层进行登录校验?

🔒 遇到的实际问题:

  • 用户请求直接打到某个微服务,绕过了登录认证;
  • 每个服务都实现登录校验,代码冗余、安全隐患大;
  • 缺乏统一认证体系,权限边界模糊;
  • 无法集中管理黑名单、权限控制等安全规则。

✅ 网关统一登录校验的优势:

优点 说明
安全性高 所有请求必须经过网关,避免绕过
易于维护 登录校验逻辑集中处理
可扩展性强 支持多种认证方式,如 JWT、Session、OAuth2
支持 Token 鉴权 JWT 无状态、跨服务使用
降低服务耦合度 各服务只关注业务逻辑,不再处理认证

二、实战演示:Gateway + JWT 登录拦截实现

🔐 推荐方案:JWT(JSON Web Token)

  • 前端登录成功后,认证服务返回 JWT Token;
  • Token 存储在前端本地(localStorage / cookie);
  • 所有请求都在 Header 中携带 Token;
  • 网关拦截并解析 Token,验证其合法性;
  • 若合法则放行请求,否则返回 401 未授权。

1️⃣ 引入依赖

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

2️⃣ JWT 工具类

public class JwtUtil {
    private static final String SECRET = "MySecretKey";

    public static Claims parseToken(String token) throws Exception {
        return Jwts.parser()
            .setSigningKey(SECRET.getBytes(StandardCharsets.UTF_8))
            .parseClaimsJws(token)
            .getBody();
    }

    public static boolean isExpired(Claims claims) {
        return claims.getExpiration().before(new Date());
    }
}

3️⃣ 编写网关登录过滤器(GlobalFilter)

@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    private static final List<String> whiteList = Arrays.asList(
        "/login", "/register", "/actuator/**"
    );

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();

        // 白名单放行
        if (whiteList.stream().anyMatch(path::startsWith)) {
            return chain.filter(exchange);
        }

        // 获取 Authorization 头
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (StringUtils.hasText(token) && token.startsWith("Bearer ")) {
            token = token.replace("Bearer ", "");
            try {
                Claims claims = JwtUtil.parseToken(token);
                if (!JwtUtil.isExpired(claims)) {
                    // Token 有效,放行
                    return chain.filter(exchange);
                }
            } catch (Exception e) {
                // Token 非法或异常
            }
        }

        // 拦截并返回 401
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }

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

4️⃣ 配置白名单和跨域支持(可选)

@Configuration
public class CorsGlobalConfig {
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        config.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
}

三、常见问题与处理建议

问题 解决方案
前端跨域无法访问 Gateway 接口 配置 CORS
Token 解析失败或过期 返回 401 并提示重新登录
微服务之间需要用户信息 可通过请求头传递用户ID、角色等信息
白名单路径过多 可集中配置在 application.yml 或配置中心

网站公告

今日签到

点亮在社区的每一天
去签到