处理CORS后请求未进入@WebFilter引发401错误求解决方案
问题分析与解决方案
问题根因
你添加的WebSecurityConfig启用了Spring Security的过滤器链,它的优先级远高于普通的@WebFilter注解的过滤器。这导致你的自定义AuthorisationFilter完全没机会处理请求,所有请求都被Spring Security默认的httpBasic认证拦截,所以返回401未授权。
具体修复步骤
1. 调整自定义过滤器的注册方式
移除AuthorisationFilter上的@WebFilter注解,改成让Spring管理这个过滤器(比如加@Component),然后把它加入到Spring Security的过滤器链中。
2. 修改WebSecurityConfig配置
@Configuration @EnableWebSecurity public class WebSecurityConfig { private final AuthorisationFilter authorisationFilter; // 构造注入自定义过滤器 public WebSecurityConfig(AuthorisationFilter authorisationFilter) { this.authorisationFilter = authorisationFilter; } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .cors(Customizer.withDefaults()) .authorizeRequests(auth -> auth.anyRequest().authenticated()) // 关闭不需要的httpBasic认证 .httpBasic(httpBasic -> httpBasic.disable()) // 将自定义过滤器添加到Security链中,位置根据你的认证逻辑调整,这里放在用户名密码过滤器之后 .addFilterAfter(authorisationFilter, UsernamePasswordAuthenticationFilter.class) .build(); } @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("http://localhost:8081")); configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PATCH", "DELETE", "OPTIONS")); // 补充常用请求头,比如Content-Type configuration.setAllowedHeaders(List.of("Authorization", "Content-Type")); // 如果前端需要携带cookie,开启这个配置(前端也要对应设置withCredentials: true) configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } }
3. 确保自定义过滤器逻辑正确
检查你的AuthorisationFilter,确保它能正确解析Authorization头,并将认证信息存入SecurityContextHolder,示例逻辑如下:
@Component public class AuthorisationFilter extends OncePerRequestFilter { // 替换成你实际的JWT工具类或认证逻辑依赖 private final JwtTokenUtil jwtTokenUtil; public AuthorisationFilter(JwtTokenUtil jwtTokenUtil) { this.jwtTokenUtil = jwtTokenUtil; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String authHeader = request.getHeader("Authorization"); if (authHeader != null && authHeader.startsWith("Bearer ")) { String token = authHeader.substring(7); String username = jwtTokenUtil.extractUsername(token); // 仅当当前无认证信息时处理 if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { // 根据实际情况构造认证对象,填充用户权限 UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( username, null, Collections.emptyList() ); authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authToken); } } filterChain.doFilter(request, response); } }
额外注意事项
- OPTIONS预请求会被Spring Security自动处理,只要CORS配置正确就无需额外放行
- 如果前端需要发送cookie,必须同时开启后端的
setAllowCredentials(true)和前端请求的withCredentials: true
内容的提问来源于stack exchange,提问作者Bungle1981
相关产品推荐
相关产品推荐

