Jetty 11本地网络访问CORS问题:自定义过滤器无法处理预检请求
解决Jetty 11自定义CORS过滤器无法处理预检请求的问题
你的自定义过滤器无法处理预检请求,核心问题在于过滤器未覆盖OPTIONS请求类型,以及响应头配置的细节缺失。以下是修正后的实现方案:
修正后的自定义CORS过滤器代码
FilterHolder corsFilter = new FilterHolder(new Filter() { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; // 动态匹配允许的请求源(替代硬编码,更灵活) String origin = request.getHeader("Origin"); if ("https://ccs-dev.cipher.kiev.ua".equals(origin)) { response.setHeader("Access-Control-Allow-Origin", origin); } // 预检请求必需的响应头 response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); response.setHeader("Access-Control-Allow-Headers", "Content-Type"); response.setHeader("Access-Control-Allow-Private-Network", "true"); // 缓存预检请求结果,减少重复OPTIONS请求 response.setHeader("Access-Control-Max-Age", "3600"); // 直接处理OPTIONS预检请求,无需转发到后端服务 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_NO_CONTENT); return; } chain.doFilter(req, res); } @Override public void init(FilterConfig filterConfig) {} @Override public void destroy() {} }); // 显式指定过滤器要处理的请求类型,确保覆盖预检OPTIONS请求 contextHandler.addFilter(corsFilter, "/*", EnumSet.of(DispatcherType.REQUEST, DispatcherType.OPTIONS));
关键修正说明
- 指定DispatcherType:原代码中
addFilter第三个参数传null,Jetty默认仅处理REQUEST类型请求,而预检OPTIONS请求属于OPTIONS类型,必须显式声明才能被过滤器捕获。 - 动态源匹配:避免硬编码请求源,通过读取请求头校验后设置响应头,适配后续域名变更场景。
- 添加缓存头:
Access-Control-Max-Age让浏览器缓存预检结果,减少重复OPTIONS请求开销。 - 直接返回OPTIONS请求:预检请求无需传递到后端Servlet,直接返回204状态码即可。
额外注意事项
- 若之前配置过Jetty自带的
CrossOriginFilter,请彻底移除,避免多个CORS过滤器冲突。 - 测试时可通过浏览器开发者工具的网络面板查看OPTIONS请求的响应头,确认
Access-Control-Allow-Private-Network是否正确返回。
内容的提问来源于stack exchange,提问作者Bondar Anton
相关产品推荐
相关产品推荐

