Spring Security CORS不生效,请求返回403/401问题求助
Spring Security跨域+认证问题:401/403排查与解决
问题核心原因
- 未配置
http.cors()时返回401:Spring Security的认证过滤器优先级高于默认CORS过滤器,Angular发起跨域请求时,浏览器会先发送OPTIONS预检请求,该请求不会携带任何认证令牌(比如JWT),直接被认证过滤器判定为未授权,返回401。 - 禁用CORS或自定义Bean无效时返回403:配置
cors(cors->cors.disable())会直接关闭Spring Security的CORS支持,浏览器触发同源策略拦截请求返回403;同时你定义的CorsConfigurationSourceBean会因CORS被禁用而完全不生效。
正确配置示例
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http)throws Exception { http .csrf(AbstractHttpConfigurer::disable) // 启用CORS,并指定使用自定义配置源 .cors(cors -> cors.configurationSource(corsConfigurationSource())) .authorizeHttpRequests(r -> r // 优先放行所有OPTIONS预检请求,避免认证拦截 .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() .anyRequest().authenticated()); return http.build(); } @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); // 允许Angular所在的源跨域 configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200")); // 包含预检请求的OPTIONS方法 configuration.setAllowedMethods(Arrays.asList("GET","POST","OPTIONS")); // 允许携带认证头、内容类型头等关键请求头 configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type")); // 允许浏览器暴露后端返回的自定义响应头(按需配置) configuration.setExposedHeaders(Arrays.asList("X-Custom-Header")); // 如果需要携带Cookie或凭证,必须开启此项(Angular端需同步设置withCredentials: true) configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } }
请求头相关关键说明
- OPTIONS预检请求:跨域场景下,浏览器会先发送OPTIONS请求确认后端是否允许跨域,该请求不携带任何用户凭证,必须在Security规则中优先放行,否则会被认证逻辑拦截。
- AllowedHeaders配置:必须包含前端请求中实际携带的所有自定义头,比如
Authorization(JWT认证时前端会把token放在这个头里)、Content-Type(发送JSON格式数据时必需),缺少的话浏览器会直接拒绝发送实际请求。 - AllowCredentials:如果你的认证依赖Cookie,或者需要前端携带凭证请求,必须开启该选项,同时Angular的HTTP请求要设置
withCredentials: true,否则浏览器不会保存或发送相关凭证。 - CORS过滤器顺序:启用
http.cors()后,Spring Security会自动将CORS过滤器置于认证过滤器之前,确保跨域规则先被校验,再执行认证逻辑,避免预检请求被误拦截。
额外注意事项
- 如果Angular请求配置了
withCredentials: true,setAllowedOrigins不能设置为*,必须指定具体的源(比如http://localhost:4200),否则浏览器会拒绝跨域请求。 - 无需修改
/**路径,该配置表示所有接口都应用跨域规则,符合你的场景需求。
内容的提问来源于stack exchange,提问作者Steve Torres
相关产品推荐
相关产品推荐

