You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot微服务中基于JWT的认证授权高效组织方案咨询

微服务认证架构落地指南(针对你的Spring Boot场景)

一、请求流向的最佳实践:先过认证,再到业务服务

别搞反了!绝对不能让请求先到业务服务再去校验认证,原因很简单:

  • 每个业务服务都要重复写认证校验逻辑,代码冗余,维护成本高;
  • 万一某个业务服务漏了校验,直接暴露业务接口,风险极大;
  • 认证逻辑集中处理,才能统一控制权限规则、错误返回(比如401/403)。

正确的流向分两种,对应不同阶段的架构:

  1. 入门阶段(无API网关):客户端请求 → 业务服务 → 业务服务调用认证服务校验Token → 校验通过则处理业务
  2. 规范微服务阶段(有API网关):客户端请求 → API网关 → 网关调用认证服务校验Token → 校验通过转发到对应业务服务

二、无API网关的落地步骤(适合新手快速上手)

你已经有了认证服务,先从这个方式入手,门槛低:

1. 给认证服务加Token校验接口

在认证服务里新增一个接口,专门用来校验JWT有效性并返回用户信息:

@RestController
@RequestMapping("/auth")
public class AuthController {
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @PostMapping("/validate")
    public ResponseEntity<AuthResponse> validateToken(@RequestBody TokenRequest request) {
        String token = request.getToken();
        if (!jwtTokenUtil.validateToken(token)) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
        }
        UserDetails userDetails = jwtTokenUtil.getUserFromToken(token);
        return ResponseEntity.ok(new AuthResponse(userDetails.getUsername(), userDetails.getAuthorities()));
    }
}

注意:用户登出时,要把失效Token加入Redis黑名单,校验前先查黑名单,防止盗用。

2. 业务服务里加认证过滤器

在业务服务的Spring Security配置中,添加自定义Filter,在请求到达业务接口前完成认证:

@Component
public class AuthValidationFilter extends OncePerRequestFilter {
    @Autowired
    private AuthFeignClient authFeignClient;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 从HttpOnly Cookie中提取Token
        String token = null;
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("accessToken".equals(cookie.getName())) {
                    token = cookie.getValue();
                    break;
                }
            }
        }

        if (token == null) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Missing token");
            return;
        }

        // 调用认证服务校验Token
        try {
            AuthResponse authResponse = authFeignClient.validateToken(new TokenRequest(token));
            // 构造认证对象并放入SecurityContext
            List<GrantedAuthority> authorities = authResponse.getAuthorities().stream()
                    .map(SimpleGrantedAuthority::new)
                    .collect(Collectors.toList());
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                    authResponse.getUsername(), null, authorities);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (FeignException e) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token");
            return;
        }

        filterChain.doFilter(request, response);
    }
}

然后在Spring Security配置中把这个Filter前置:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
    @Autowired
    private AuthValidationFilter authValidationFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .addFilterBefore(authValidationFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }
}

3. 服务间调用工具:OpenFeign

用OpenFeign调用认证服务接口,比RestTemplate更符合Spring风格:
先在业务服务pom.xml加依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

然后写FeignClient接口:

@FeignClient(name = "auth-service", url = "http://localhost:8080")
public interface AuthFeignClient {
    @PostMapping("/auth/validate")
    AuthResponse validateToken(@RequestBody TokenRequest request);
}

记得在启动类加@EnableFeignClients注解。

三、API网关的落地拆解(从抽象到具体)

等熟悉无网关模式后,再升级到API网关,这是微服务的标准方案:

1. 新建Spring Cloud Gateway项目

加核心依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2. 网关里加全局认证Filter

校验逻辑和业务服务类似,但校验完成后直接转发到业务服务,无需处理业务:

@Component
public class GatewayAuthFilter implements GlobalFilter, Ordered {
    @Autowired
    private AuthFeignClient authFeignClient;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        // 从Cookie提取Token
        String token = null;
        HttpCookie cookie = request.getCookies().getFirst("accessToken");
        if (cookie != null) {
            token = cookie.getValue();
        }

        if (token == null) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        // 调用认证服务校验Token,校验通过后携带用户信息转发
        return authFeignClient.validateToken(new TokenRequest(token))
                .map(authResponse -> {
                    ServerHttpRequest modifiedRequest = request.mutate()
                            .header("X-User-Name", authResponse.getUsername())
                            .header("X-User-Authorities", authResponse.getAuthorities().toString())
                            .build();
                    return exchange.mutate().request(modifiedRequest).build();
                })
                .flatMap(chain::filter)
                .onErrorResume(e -> {
                    exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                    return exchange.getResponse().setComplete();
                });
    }

    @Override
    public int getOrder() {
        return -100; // 确保该Filter优先执行
    }
}

3. 配置路由规则

在application.yml中设置转发规则:

spring:
  cloud:
    gateway:
      routes:
        - id: user-service-route
          uri: http://localhost:8081
          predicates:
            - Path=/api/user/**
        - id: order-service-route
          uri: http://localhost:8082
          predicates:
            - Path=/api/order/**

客户端请求http://网关地址/api/user/info时,网关会自动转发到用户业务服务,且已完成认证。

四、关键最佳实践提醒

  • 认证服务单一职责:只做注册、登录、Token生成/校验、登出,不要掺杂业务逻辑,方便后续扩展。
  • Token生命周期管理:accessToken设为15分钟左右,refreshToken设为7天,登录时返回两个HttpOnly Cookie,accessToken过期后用refreshToken换新的accessToken。
  • 服务发现替换硬编码:后续服务增多后,用Eureka或Nacos做服务发现,FeignClient直接用服务名调用(比如@FeignClient(name = "auth-service"))。

内容的提问来源于stack exchange,提问作者Georgi Babov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 21:28:14