调用OPTIONS接口http://10.100.8.58:8080/user/view返回401,求排查CORS过滤器问题
从你的问题描述和未完成的CORS过滤器代码来看,这个401错误的核心原因通常是浏览器发送的OPTIONS预检请求被服务器的认证机制拦截了——因为OPTIONS请求是浏览器自动发起的,不会携带你的认证凭证(比如Token、Cookie),但你的服务器可能把它当成了需要认证的普通请求,所以返回了401。
下面是具体的排查和修复步骤:
1. 确保CORS过滤器优先执行
如果你的项目里有认证相关的过滤器(比如Spring Security的过滤器、自定义JWT过滤器),CORS过滤器必须在这些过滤器之前运行,否则OPTIONS请求还没被处理就被认证拦截器挡下来了。
比如在Spring Boot中,给你的SimpleCorsFilter加上最高优先级的注解:
import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Order(Ordered.HIGHEST_PRECEDENCE) // 让这个过滤器最先执行 public class SimpleCorsFilter implements Filter { // ... 你的其他代码 }
2. 完善CORS过滤器的OPTIONS请求处理
你的代码只写了一半,需要补全逻辑:直接处理OPTIONS请求,返回必要的CORS头并终止过滤器链,不要让它走到认证环节。完整的过滤器代码应该是这样:
@Order(Ordered.HIGHEST_PRECEDENCE) public class SimpleCorsFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; // 设置允许的源、方法、自定义头 response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); response.setHeader("Access-Control-Max-Age", "3600"); // 预检请求缓存时间,减少重复请求 response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, X-Requested-With"); // 处理OPTIONS预检请求:直接返回200 OK,不需要走后续认证流程 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); return; // 终止过滤器链,避免触发认证 } // 非OPTIONS请求,继续执行后续过滤器(包括认证) chain.doFilter(req, res); } @Override public void destroy() { } }
3. 检查认证配置,排除OPTIONS请求
如果你的项目用了Spring Security这类框架,还要在安全配置里明确允许所有OPTIONS请求无需认证:
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.http.HttpMethod; @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 允许所有OPTIONS请求 .anyRequest().authenticated() // 其他认证相关配置(比如JWT、Basic Auth)... } }
为什么这么做?
浏览器在发送跨域的非简单请求(比如带自定义头、PUT/DELETE方法的请求)之前,会自动发送OPTIONS预检请求,询问服务器是否允许该跨域请求。这个请求不会携带任何认证信息,所以服务器必须允许OPTIONS请求匿名访问,否则就会返回401。
按照上面的步骤调整后,再测试OPTIONS请求应该就能返回200,后续的实际请求也能正常处理了。
内容的提问来源于stack exchange,提问作者Suriyan
相关产品推荐
相关产品推荐

