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

Spring WebFlux WebFilter校验JWT时无法返回JSON格式响应

解决Spring WebFlux WebFilter返回JSON格式错误响应的问题

我懂你现在遇到的问题了——在Spring WebFlux的WebFilter里做JWT请求头校验,校验不通过时虽然能返回响应,但格式不是预期的JSON,对吧?核心问题在于你没有手动设置响应的Content-Type头,也没有把错误信息序列化为JSON写入响应体。下面是具体的解决思路和代码示例:

1. 先定义统一的错误响应DTO

首先创建一个简单的错误信息封装类,用来规范错误返回的结构:

public class ErrorResponse {
    private int statusCode;
    private String message;

    // 构造方法
    public ErrorResponse(int statusCode, String message) {
        this.statusCode = statusCode;
        this.message = message;
    }

    // 省略getter、setter方法
}

2. 修改WebFilter的filter方法逻辑

在校验失败时,手动设置响应状态码、Content-Type头,再把错误对象序列化为JSON写入响应体:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

public class JwtAuthFilter implements WebFilter {

    // 注入Jackson的ObjectMapper,用于序列化JSON
    private final ObjectMapper objectMapper;

    public JwtAuthFilter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String path = request.getPath().pathWithinApplication().value();

        // 你的JWT校验逻辑示例:获取Authorization头并校验
        String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        boolean isValidJwt = validateJwtToken(authHeader); // 替换成你的实际校验方法

        if (!isValidJwt) {
            // 1. 设置响应状态码,比如401未授权
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            // 2. 设置Content-Type为application/json,告诉客户端这是JSON响应
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

            // 3. 创建错误响应对象
            ErrorResponse errorResponse = new ErrorResponse(
                HttpStatus.UNAUTHORIZED.value(),
                "无效或缺失的JWT Token"
            );

            // 4. 序列化错误对象为字节流,写入响应体
            return response.writeWith(Mono.fromSupplier(() -> {
                try {
                    byte[] jsonBytes = objectMapper.writeValueAsBytes(errorResponse);
                    return response.bufferFactory().wrap(jsonBytes);
                } catch (Exception e) {
                    // 序列化失败时返回空字节流(实际项目里可以加日志)
                    return response.bufferFactory().wrap(new byte[0]);
                }
            }));
        }

        // 校验通过,继续执行过滤器链
        return chain.filter(exchange);
    }

    // 模拟JWT校验方法,替换成你的实际校验逻辑
    private boolean validateJwtToken(String authHeader) {
        return authHeader != null && authHeader.startsWith("Bearer ") && authHeader.length() > 7;
    }
}

3. 关键注意点

  • 必须设置Content-Type: application/json,否则客户端无法识别响应为JSON格式
  • 使用ObjectMapper将错误对象序列化为字节数组,通过response.bufferFactory().wrap()生成响应所需的DataBuffer
  • 用response.writeWith()返回包含响应体的Mono<Void>,而不是直接返回Mono.empty()

这样修改后,当JWT校验失败时,就会返回标准的JSON格式响应,示例如下:

{
  "statusCode": 401,
  "message": "无效或缺失的JWT Token"
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:01:25