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

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);
  }
}

问题分析与解决步骤

可能原因

  1. 端点匹配规则错误:GraphQL默认仅暴露/graphql单个端点,配置中使用的/graphql/**通配符可能导致规则不匹配,移出白名单后被Spring Security直接拦截;
  2. JWT过滤器未生效:需确认GraphQL请求是否携带了正确的Authorization头,以及过滤器是否实际执行了认证逻辑;
  3. 用户权限缺失:即使JWT认证通过,若用户无对应权限,也会返回403。

解决步骤

  1. 修正端点匹配规则
    将安全配置中的端点匹配改为/graphql(去掉通配符),修改后代码片段:

    .authorizeHttpRequests(
            authorizeRequests ->
                    authorizeRequests
                            .requestMatchers("/graphql")
                            .authenticated()
                            .anyRequest().authenticated()
    )
    
  2. 验证过滤器执行情况
    在JWT过滤器关键位置添加日志,确认请求是否被处理:

    // 提取Authorization头后添加
    System.out.println("处理请求:" + request.getRequestURI() + ",Authorization头:" + authHeader);
    // 认证成功后添加
    System.out.println("用户认证成功:" + userEmail);
    

    发起GraphQL请求后,查看控制台日志,确认过滤器是否执行、Token是否被正确解析。

  3. 补全用户权限配置
    检查UserDetails实现类的getAuthorities()方法,确保返回至少一个有效权限,示例:

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return List.of(new SimpleGrantedAuthority("ROLE_USER"));
    }
    
  4. 调整权限校验规则
    若认证成功仍返回403,可在安全配置中明确指定GraphQL端点的权限要求:

    .authorizeHttpRequests(
            authorizeRequests ->
                    authorizeRequests
                            .requestMatchers("/graphql")
                            .hasAnyRole("USER")
                            .anyRequest().authenticated()
    )
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 14:32:35