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

如何通过Filter为HttpServletRequest添加自定义请求头?

如何在Filter中为HttpServletRequest添加自定义请求头

你遇到的问题很典型——原生的HttpServletRequest是只读设计,没有提供直接修改或添加请求头的方法,因为它是对底层HTTP请求的封装,规范上不允许随意篡改原始请求数据。虽然你看到Tomcat的CoyoteRequest内部有请求头列表,但直接操作它属于依赖容器私有实现,耦合性极高,换用Jetty等其他Web容器就会失效,非常不推荐。

正确的做法是使用**HttpServletRequestWrapper**包装原始请求,通过重写相关方法注入自定义请求头,这是Servlet规范提供的标准解决方案,兼容性拉满。

步骤1:自定义HttpServletRequestWrapper子类

创建一个包装类,重写获取请求头的方法,把自定义请求头和原始请求头整合在一起:

public class CustomHeaderRequestWrapper extends HttpServletRequestWrapper {
    private final Map<String, String> customHeaders;

    public CustomHeaderRequestWrapper(HttpServletRequest request) {
        super(request);
        this.customHeaders = new HashMap<>();
    }

    // 提供添加自定义请求头的方法
    public void addCustomHeader(String name, String value) {
        customHeaders.put(name, value);
    }

    @Override
    public String getHeader(String name) {
        // 优先返回自定义请求头,没有则用原始请求的
        String customHeader = customHeaders.get(name);
        if (customHeader != null) {
            return customHeader;
        }
        return super.getHeader(name);
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        List<String> headers = new ArrayList<>();
        String customHeader = customHeaders.get(name);
        if (customHeader != null) {
            headers.add(customHeader);
        }
        // 合并原始请求的同名称头信息
        Enumeration<String> originalHeaders = super.getHeaders(name);
        while (originalHeaders.hasMoreElements()) {
            headers.add(originalHeaders.nextElement());
        }
        return Collections.enumeration(headers);
    }

    @Override
    public Enumeration<String> getHeaderNames() {
        Set<String> headerNames = new HashSet<>(customHeaders.keySet());
        // 合并原始请求的所有头名称
        Enumeration<String> originalHeaderNames = super.getHeaderNames();
        while (originalHeaderNames.hasMoreElements()) {
            headerNames.add(originalHeaderNames.nextElement());
        }
        return Collections.enumeration(headerNames);
    }
}

步骤2:在CorsFilter中使用包装类修改请求

修改你的CorsFilter的doFilter方法,用自定义包装类包裹原始请求,添加自定义头后再传给过滤器链:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        System.out.println("--------------------------------------");
        HttpServletRequest request = (HttpServletRequest) req;
        // 用自定义包装类包裹原始请求
        CustomHeaderRequestWrapper wrappedRequest = new CustomHeaderRequestWrapper(request);
        // 添加自定义请求头
        wrappedRequest.addCustomHeader("X-Custom-Header", "your-custom-value");
        
        final HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        // 别忘了把自定义头加入跨域允许列表
        response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Custom-Header");
        response.setHeader("Access-Control-Max-Age", "3600");
        
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            // 传递包装后的请求到后续过滤器/处理器
            chain.doFilter(wrappedRequest, res);
        }
    }
}

补充说明

  • 你之前用req.setAttribute("test", "test")是往请求的属性中存储数据,这和请求头是两个概念:属性是服务器内部传递数据的载体,而请求头是HTTP协议层面的字段,前端或后续处理器需要通过getHeader方法获取。
  • 跨域场景下必须把自定义请求头加入Access-Control-Allow-Headers,否则浏览器会拦截这个头信息,导致请求失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:07:53