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

Spring GraphQL如何跳过introspection查询的鉴权逻辑

注意:内省查询会暴露全量Schema结构,存在安全风险,跳过鉴权放开内省的逻辑请仅在开发/测试环境使用,生产环境建议直接关闭内省能力。

方案1:快速适配(适合不想改动现有鉴权结构的开发场景)

直接利用GraphiQL可自定义请求头的能力做白名单判断,不需要解析GraphQL请求,实现成本最低:

  1. 在配置文件中给GraphiQL界面发起的所有请求加上固定标识头:
spring:
  graphql:
    graphiql:
      enabled: true
      headers:
        X-GraphiQL-Request: "true"
  1. 在你的AuthFilter中优先判断请求头和路径,匹配则直接放行:
public class AuthFilter implements WebFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().value();
        // 放行GraphiQL静态资源、带GraphiQL标识头的请求
        if (path.startsWith("/graphiql") 
            || "true".equals(request.getHeaders().getFirst("X-GraphiQL-Request"))) {
            return chain.filter(exchange);
        }

        // 原有鉴权逻辑
        // ...
        return chain.filter(exchange);
    }
}

该方案基于请求头做信任判断,生产环境必须移除相关配置,避免攻击者伪造请求头绕过鉴权。


方案2:规范实现(推荐,无安全隐患)

WebFilter属于通用Web层组件,本身不感知GraphQL语义,不要在这一层解析GraphQL查询内容,应该把GraphQL相关的鉴权逻辑下沉到Spring GraphQL自带的扩展点,和Web层逻辑解耦:

  1. 调整AuthFilter,直接放行GraphQL相关端点,这部分请求的鉴权交给GraphQL专用拦截器处理:
public class AuthFilter implements WebFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        String path = exchange.getRequest().getPath().value();
        // 放行GraphiQL静态资源、GraphQL端点,不做Web层鉴权
        if (path.startsWith("/graphiql") || path.equals("/graphql")) {
            return chain.filter(exchange);
        }

        // 其他非GraphQL请求走原有鉴权逻辑
        // ...
        return chain.filter(exchange);
    }
}
  1. 自定义WebGraphQlInterceptor处理GraphQL请求鉴权,在这里可以通过AST语法树精准识别纯内省查询,只对这类查询跳过鉴权,不存在误判:
@Component
public class GraphQlAuthInterceptor implements WebGraphQlInterceptor {
    // 仅在GraphiQL开启时(开发环境)生效内省放行逻辑
    @Value("${spring.graphql.graphiql.enabled:false}")
    private boolean allowIntrospectionNoAuth;

    @Override
    public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, WebGraphQlChain chain) {
        if (allowIntrospectionNoAuth && isPureIntrospectionQuery(request.getDocument())) {
            return chain.next(request);
        }

        // 其余GraphQL请求走原有鉴权逻辑,校验完成后可将用户信息写入GraphQL上下文
        // ... 鉴权逻辑
        return chain.next(request);
    }

    /**
     * 判断当前查询是否为纯内省查询(仅查询__schema/__type字段,无业务字段)
     */
    private boolean isPureIntrospectionQuery(Document document) {
        for (Definition definition : document.getDefinitions()) {
            if (!(definition instanceof OperationDefinition opDef)) {
                continue;
            }
            for (Selection selection : opDef.getSelectionSet().getSelections()) {
                if (!(selection instanceof Field field)) {
                    return false;
                }
                String name = field.getName();
                // 包含任何非内省根字段,就需要走鉴权
                if (!"__schema".equals(name) && !"__type".equals(name)) {
                    return false;
                }
            }
        }
        return true;
    }
}

避坑提醒

不要直接在WebFilter中读取/graphql端点的请求体来判断是不是内省查询:WebFlux的请求体是单次消费的流,直接读取后如果没有做缓存包装,后续Spring GraphQL层会因为读不到请求体直接报错。如果一定要在WebFilter层做解析,必须先通过ServerWebExchangeUtils.cacheRequestBodyAndRequest缓存请求体,维护成本很高,不推荐。

生产环境如果不需要对外提供Schema文档能力,直接关闭内省即可,不需要配置放行逻辑:

spring:
  graphql:
    schema:
      introspection:
        enabled: false

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 01:24:21