Spring Boot网关中Spring Security默认登录页无法禁用及JWT令牌校验配置问题
解决Spring Cloud Gateway中JWT过滤器配置后仍重定向到默认登录页的问题
嘿,我看你遇到的问题核心出在Spring Cloud Gateway的技术栈适配上,咱们一步步来解决:
核心问题根源
Spring Cloud Gateway是基于WebFlux的响应式框架,而你用的WebSecurityConfigurerAdapter是Servlet环境下的Spring Security配置类——这俩根本不兼容!所以你的自定义安全配置完全没生效,系统还是走了默认的Servlet版Spring Security逻辑,才会把未认证请求重定向到/login。
正确的配置方案(WebFlux版Security)
你需要换成响应式的Spring Security配置,用@EnableWebFluxSecurity替代@EnableWebSecurity,并通过SecurityWebFilterChain Bean来定义规则,同时适配WebFlux的过滤器逻辑:
@Configuration @EnableWebFluxSecurity public class SecurityTokenConfig { private static final Logger logger = LoggerFactory.getLogger(SecurityTokenConfig.class); private final JwtConfig jwtConfig; // 构造注入你的JwtConfig实例 public SecurityTokenConfig(JwtConfig jwtConfig) { this.jwtConfig = jwtConfig; } @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { return http // 禁用CSRF,无状态JWT场景不需要 .csrf(ServerHttpSecurity.CsrfSpec::disable) // 设置会话为无状态 .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 自定义未认证处理:直接返回401,不重定向 .exceptionHandling(exceptions -> exceptions .authenticationEntryPoint((exchange, ex) -> { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); })) // 添加JWT认证过滤器,放在认证阶段 .addFilterAt(jwtAuthenticationFilter(), SecurityWebFiltersOrder.AUTHENTICATION) // 路径授权规则:放行指定路径,其余都需要认证 .authorizeExchange(exchanges -> exchanges .pathMatchers("/**/auth-api/**").permitAll() .anyExchange().authenticated()) .build(); } // 适配WebFlux的JWT过滤器逻辑 private ServerWebExchangeFilterFunction jwtAuthenticationFilter() { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest(); String token = extractTokenFromRequest(request); if (token != null && jwtConfig.validateToken(token)) { // 解析Token并构造Authentication对象 String username = jwtConfig.getUsernameFromToken(token); Collection<? extends GrantedAuthority> authorities = jwtConfig.getAuthoritiesFromToken(token); Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, authorities); // 将认证信息放入请求上下文 return chain.filter(exchange.mutate() .principal(authentication) .build()); } // 允许的路径直接放行,其余进入未认证处理 if (exchange.getRequest().getPath().match("/**/auth-api/**")) { return chain.filter(exchange); } else { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } }; } // 从请求头提取JWT Token(示例:Authorization: Bearer xxx) private String extractTokenFromRequest(ServerHttpRequest request) { String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION); if (authHeader != null && authHeader.startsWith("Bearer ")) { return authHeader.substring(7); } return null; } }
额外需要注意的点
- 依赖检查:确保你的网关项目只引入了
spring-cloud-starter-gateway依赖,不要同时引入spring-boot-starter-web(Web和WebFlux不能共存,否则会自动切换到Servlet环境,导致Gateway功能异常)。 - 自动配置排除:如果你之前加了
exclude = { SecurityAutoConfiguration.class },可以保留,但换成WebFlux版配置后,这个排除其实不是必须的,按需调整即可。 - JwtConfig适配:你的
JwtConfig不需要大改,只需要确保validateToken、getUsernameFromToken等方法逻辑正常即可。
这样配置后,就不会再出现重定向到默认登录页的问题,只有/**/auth-api/**路径会被放行,其他路径都会先经过JWT校验,校验失败直接返回401。
内容的提问来源于stack exchange,提问作者YK mar
相关产品推荐
相关产品推荐

