Spring Boot中GraphQL接口持有效JWT仍返回403权限问题
问题:Spring Boot GraphQL端点JWT认证返回403错误
场景概述
我有一个Spring Boot项目,REST接口通过JWT过滤器实现安全验证——比如GET请求携带Bearer Token即可返回用户数据,所有REST接口均正常工作。现在要新增GraphQL查询用于数据获取,却遇到了认证问题。
问题现象
- 若将
/graphql/**加入安全配置白名单,GraphQL查询可正常执行并获取数据; - 移出白名单后,无论请求是否携带有效访问令牌,都会返回403状态码,且Postman、IntelliJ控制台均无可用的错误追溯信息。
现有配置代码
安全配置类
@Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig { private final JwtAuthenticationFilter jwtAuthenticationFilter; private final AuthenticationProvider authenticationProvider; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { return httpSecurity .csrf(csrf -> csrf.disable()) .authorizeHttpRequests( authorizeRequests -> authorizeRequests .requestMatchers("/graphql/**") .permitAll() .anyRequest().authenticated() ) .sessionManagement( sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authenticationProvider(authenticationProvider) .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) .build(); } }
JWT过滤器类
@Component @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtService jwtService; private final UserDetailsService userDetailsService; @Override protected void doFilterInternal( @NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException { final String authHeader = request.getHeader("Authorization"); final String jwt; final String userEmail; if (authHeader == null || !authHeader.startsWith("Bearer ")) { filterChain.doFilter(request, response); return; } jwt = authHeader.substring(7);// beginIndex is 7 bc "Bearer " is 7 userEmail = jwtService.extractUserEmail(jwt); if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) { // check if user is already authenticated UserDetails userDetails = userDetailsService.loadUserByUsername(userEmail); if (jwtService.isTokenValid(jwt, userDetails)) { UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authToken); } } filterChain.doFilter(request, response); } }
问题分析与解决步骤
可能原因
- 端点匹配规则错误:GraphQL默认仅暴露
/graphql单个端点,配置中使用的/graphql/**通配符可能导致规则不匹配,移出白名单后被Spring Security直接拦截; - JWT过滤器未生效:需确认GraphQL请求是否携带了正确的
Authorization头,以及过滤器是否实际执行了认证逻辑; - 用户权限缺失:即使JWT认证通过,若用户无对应权限,也会返回403。
解决步骤
修正端点匹配规则
将安全配置中的端点匹配改为/graphql(去掉通配符),修改后代码片段:.authorizeHttpRequests( authorizeRequests -> authorizeRequests .requestMatchers("/graphql") .authenticated() .anyRequest().authenticated() )验证过滤器执行情况
在JWT过滤器关键位置添加日志,确认请求是否被处理:// 提取Authorization头后添加 System.out.println("处理请求:" + request.getRequestURI() + ",Authorization头:" + authHeader); // 认证成功后添加 System.out.println("用户认证成功:" + userEmail);发起GraphQL请求后,查看控制台日志,确认过滤器是否执行、Token是否被正确解析。
补全用户权限配置
检查UserDetails实现类的getAuthorities()方法,确保返回至少一个有效权限,示例:@Override public Collection<? extends GrantedAuthority> getAuthorities() { return List.of(new SimpleGrantedAuthority("ROLE_USER")); }调整权限校验规则
若认证成功仍返回403,可在安全配置中明确指定GraphQL端点的权限要求:.authorizeHttpRequests( authorizeRequests -> authorizeRequests .requestMatchers("/graphql") .hasAnyRole("USER") .anyRequest().authenticated() )
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

