Java 21+Spring Boot 3.2+WebFlux下无法获取GraphQL请求头
WebFlux + Spring GraphQL 获取请求头(JWT)解决方案
核心问题说明
Spring GraphQL 不支持直接在 @QueryMapping/@MutationMapping 方法参数中传入 ServerHttpRequest 或 ServerWebExchange,这类请求作用域对象需要通过 GraphQL 上下文获取。
可行解决方案
1. 直接获取单个请求头(推荐简单场景)
使用 @ContextValue 注解直接提取指定请求头,无需手动处理请求对象:
import org.springframework.graphql.data.method.annotation.ContextValue; @QueryMapping public Collection<Customer> queryCustomers( @ContextValue("Authorization") String authHeader, @Argument String zipCode ) { // 提取JWT(去掉Bearer前缀) String jwt = authHeader.replaceFirst("Bearer ", ""); // 后续业务逻辑处理 return service.queryCustomers(zipCode); }
2. 通过 GraphQL 上下文获取完整请求信息
如果需要更多请求细节,注入 GraphQlContext 并从中获取 ServerHttpRequest:
import org.springframework.graphql.execution.GraphQlContext; import reactor.core.publisher.Mono; @QueryMapping public Mono<Collection<Customer>> queryCustomers( GraphQlContext context, @Argument String zipCode ) { return context.getOrEmpty(ServerHttpRequest.class) .map(request -> { String authHeader = request.getHeaders().getFirst("Authorization"); // 解析JWT、校验权限等操作 return service.queryCustomers(zipCode); }) .orElseGet(() -> { // 处理无请求对象的异常场景 return service.queryCustomers(zipCode); }); }
3. 全局拦截器统一处理JWT(推荐鉴权场景)
实现 WebGraphQlInterceptor 全局拦截请求,解析JWT后存入上下文,供所有Controller复用:
import org.springframework.graphql.server.WebGraphQlInterceptor; import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.WebGraphQlResponse; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; @Component public class JwtAuthInterceptor implements WebGraphQlInterceptor { @Override public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) { String authHeader = request.getHeaders().getFirst("Authorization"); if (authHeader != null && authHeader.startsWith("Bearer ")) { String jwt = authHeader.substring(7); // 验证JWT合法性,解析用户信息 String userId = parseUserIdFromJwt(jwt); // 将用户信息存入上下文 request.configureExecutionInput((input, builder) -> builder.graphQLContext(ctx -> ctx.put("currentUserId", userId)).build()); } return chain.next(request); } // 示例:从JWT解析用户ID的工具方法 private String parseUserIdFromJwt(String jwt) { // 实际业务中使用JWT库解析,比如JJWT return "user123"; } }
然后在Controller中直接获取上下文里的用户信息:
@QueryMapping public Collection<Customer> queryCustomers( @ContextValue("currentUserId") String userId, @Argument String zipCode ) { // 使用用户ID做业务逻辑处理 return service.queryCustomersByUserIdAndZipCode(userId, zipCode); }
为什么之前的方法失败?
- 方法参数直接传ServerHttpRequest:Spring GraphQL的方法参数解析器仅支持特定类型(如
@Argument、@ContextValue、GraphQlContext),ServerHttpRequest不在支持列表中,因此报错。 - 构造函数注入ServerHttpRequest:
ServerHttpRequest是请求作用域对象,不属于Spring容器的单例Bean,无法通过构造函数注入,必须从当前请求上下文获取。
内容的提问来源于stack exchange,提问作者Ebad
相关产品推荐
相关产品推荐

