Angular interceptor调用非公开接口报strict-origin-when-cross-origin错误如何解决
问题根因拆解
你遇到的两次请求是浏览器CORS机制触发的OPTIONS预检请求,核心问题出在后端CORS和Spring Security的配置错误,而非Angular拦截器的问题:
- 当跨域请求携带自定义头(如
Authorization)时,浏览器会自动发起OPTIONS预检请求,确认后端允许该跨域请求后才会发送真实业务请求 - 你完全关闭了Spring的CORS支持,导致后端无法正常响应OPTIONS预检请求,预检直接失败,浏览器就会阻断后续的真实业务请求,所以你会看到第二次请求未触达后端
- 公开接口未触发该问题,要么是公开接口的请求刚好符合简单请求规则无需预检,要么是你配置了公开路径放行所有请求包括OPTIONS
解决步骤
1. 后端正确配置CORS(不要完全关闭CORS支持)
完全关闭CORS的方案不适用跨域带自定义头的场景,改用如下配置:
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 替换为你的前端实际访问地址,带凭证场景不允许使用* .allowedOrigins("http://localhost:4200") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) // 预检请求缓存1小时,有效期内无需重复发起预检 .maxAge(3600); } }
2. Spring Security放行OPTIONS请求
OPTIONS请求不会携带Authorization头,会被非公开路径的鉴权规则拦截,需要单独放行:
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.cors() .and() .authorizeRequests() // 放行所有OPTIONS请求 .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() .antMatchers("/api/public/**").permitAll() .anyRequest().authenticated(); // 其余你的鉴权配置保持不变 } }
3. 优化Angular拦截器逻辑(可选,规避不必要的问题)
避免给OPTIONS请求加Authorization头,同时补全Bearer前缀(绝大多数后端鉴权逻辑要求该格式):
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<unknown>> { // OPTIONS请求直接跳过加头 if (req.method === 'OPTIONS') { return next.handle(req); } const token = this.getAccessToken(); if (token) { const authReq = req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); return next.handle(authReq); } return next.handle(req); }
配置完成后重新测试即可看到OPTIONS请求返回200状态,后续真实请求会正常携带Authorization头访问非公开接口。
内容的提问来源于stack exchange,提问作者bosznorbi
相关产品推荐
相关产品推荐

