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
相关产品推荐
相关产品推荐

