Spring Boot 3.2.0+Spring GraphQL:GraphIQL自省免鉴权配置咨询
解决方案
要实现GraphQL自省请求无需认证,而普通查询/变更请求保持鉴权,可以通过以下两种方式实现:
方式一:Spring Security请求匹配器(推荐)
通过自定义请求匹配器识别自省请求,在Security层面直接放行,性能更优。
- 自定义自省请求匹配器
import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.StreamUtils; import java.nio.charset.StandardCharsets; public class GraphQLIntrospectionMatcher implements RequestMatcher { private static final String INTROSPECTION_MARKERS = "__schema|__type"; @Override public boolean matches(HttpServletRequest request) { if (!"/graphql".equals(request.getRequestURI())) { return false; } try { String requestBody = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8); return requestBody.matches(".*(" + INTROSPECTION_MARKERS + ").*"); } catch (Exception e) { return false; } } }
- 配置Spring Security
在Security配置类中,让自省请求绕过认证,其余/graphql请求保持鉴权:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers(new GraphQLIntrospectionMatcher()).permitAll() .requestMatchers("/graphql").authenticated() .anyRequest().permitAll() ) // 替换为你实际使用的认证方式(如JWT、OAuth2等) .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(/* 自定义转换器 */))); return http.build(); } }
方式二:GraphQL拦截器处理
通过Spring GraphQL的拦截器,在查询执行前判断是否为自省请求,跳过认证检查。
- 自定义GraphQL拦截器
import org.springframework.graphql.server.WebGraphQlInterceptor; import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.WebGraphQlResponse; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.security.core.context.SecurityContextHolder; import reactor.core.publisher.Mono; public class IntrospectionAuthInterceptor implements WebGraphQlInterceptor { private static final String INTROSPECTION_MARKERS = "__schema|__type"; @Override public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) { String query = request.getDocument(); if (query != null && query.matches(".*(" + INTROSPECTION_MARKERS + ").*")) { // 自省请求直接放行 return chain.next(request); } // 非自省请求检查认证状态 var auth = SecurityContextHolder.getContext().getAuthentication(); if (auth == null || !auth.isAuthenticated()) { return Mono.error(new AuthenticationCredentialsNotFoundException("请携带认证令牌访问")); } return chain.next(request); } }
- 注册拦截器
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.graphql.server.WebGraphQlInterceptor; @Configuration public class GraphQlConfig { @Bean public WebGraphQlInterceptor introspectionAuthInterceptor() { return new IntrospectionAuthInterceptor(); } }
注意事项
- 方式一在请求进入Security过滤器时就完成判断,避免了不必要的认证流程,推荐使用;
- 方式二更贴近GraphQL业务逻辑,适合需要对请求做额外处理的场景;
- 确保GraphIQL发送的自省请求为POST方法,且请求体包含
__schema或__type关键字,匹配逻辑才能生效; - 代码中的认证配置部分需替换为你项目实际使用的方案(如JWT、Session认证等)。
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

