Spring配置@CrossOrigin后,Angular带JWT请求仍遭CORS拦截
问题原因及解决方案
带Authorization头的跨域请求会触发浏览器的预检OPTIONS请求,你当前控制器上的@CrossOrigin注解没覆盖到这个预检请求的处理,导致响应里缺失CORS相关头,所以浏览器报错。Postman不属于浏览器环境,不会发送预检请求,因此能正常调用。
以下是几种解决办法:
1. 结合Spring Security配置CORS(如果用了Security)
如果你的项目集成了Spring Security,Security过滤器链会优先于控制器的注解处理请求,所以需要在Security配置里专门放行OPTIONS请求并配置CORS:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // 启用CORS配置 .cors(cors -> cors.configurationSource(corsConfigurationSource())) .csrf(csrf -> csrf.disable()) // 若不需要CSRF保护可关闭 .authorizeHttpRequests(auth -> auth .requestMatchers("/auth/**").permitAll() // 放行认证接口 .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行所有OPTIONS预检请求 .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())); // 适配JWT认证 return http.build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Collections.singletonList("*")); config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); config.setAllowedHeaders(Collections.singletonList("*")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } }
2. 全局配置CORS(替代控制器注解)
全局配置会覆盖所有请求路径,包括预检OPTIONS请求,比控制器级别的注解更可靠:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*"); } }
注意:如果需要允许携带凭证(比如Cookie),allowedOrigins不能设为*,要指定具体的前端地址(如http://localhost:4200),同时开启allowCredentials(true)。
3. 确保控制器处理OPTIONS请求(不推荐)
如果坚持用控制器级别的注解,需要确保控制器的请求映射支持OPTIONS方法,比如:
@RestController @CrossOrigin(origins = "*", allowedHeaders = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS}) @RequestMapping("/sensors") public class SensorController { // 接口实现 }
这种方式仅作用于当前控制器,灵活性较差,一般不推荐使用。
内容的提问来源于stack exchange,提问作者Matvey Androsyuk
相关产品推荐
相关产品推荐

