彻底理解「CORS policy: No ‘Access-Control-Allow-Origin’」跨域错误
作为编程新手,在前后端联调时经常会遇到如下报错:
Access to XMLHttpRequest at 'http://localhost:8120/login' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
本文将从问题本质、产生原因和解决方案三个层面,用通俗易懂的方式讲解这个错误。
一、理解报错信息
1. 核心概念:跨域(CORS)
浏览器遵循「同源策略」:只有当请求的协议、域名和端口完全一致时,才允许前端获取后端数据,否则就是跨域请求。
以报错为例:
- 前端运行在:http://localhost:3000
- 请求后端接口:http://localhost:8120/login
由于端口不同(3000 vs 8120),属于跨域请求。若后端未配置允许跨域的响应头,浏览器就会拦截并报错。
2. 报错解析
| 报错片段 | 解释 |
|---|---|
| Access to XMLHttpRequest at ‘http://localhost:8120/login’ | 前端尝试请求后端接口 |
| from origin ‘http://localhost:3000’ | 前端源为3000端口 |
| blocked by CORS policy | 被浏览器跨域规则拦截 |
| No ‘Access-Control-Allow-Origin’ header | 后端响应缺少关键跨域头信息 |
总结:浏览器出于安全考虑阻止了跨域请求,因为后端未明确授权前端访问。
二、产生原因
浏览器设计「同源策略」是为了安全(如防止恶意网站窃取登录信息),但给开发带来不便。
跨域请求流程:
- 前端发送请求到后端
- 浏览器检查是否同源
- 对于复杂请求(如POST),浏览器先发送OPTIONS预检请求
- 若后端响应缺少Access-Control-Allow-Origin头,浏览器拦截请求
三、解决方案(按优先级)
方法1:后端配置跨域(推荐方案)
Spring Boot + Spring Security配置示例:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.requestMatchers("/api/**").permitAll()
.anyRequest().permitAll()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.formLogin(form -> form.disable());
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("http://localhost:3000");
config.setAllowCredentials(true);
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowedHeaders(Arrays.asList("*"));
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}
方法2:前端代理配置(临时方案)
当后端暂时无法修改时,前端可通过设置代理使请求"伪装"为同源请求。
Vue项目配置(基于Vite):
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:8120',
changeOrigin: true
}
}
}
});
React项目配置:
{
"proxy": "http://localhost:8120"
}
方法3:重定向问题排查
检查:
- 前端请求为何会跳转到不同端口?
- 重定向后的接口路径是否正确?
四、常见错误与解决方案
- 跨域配置层级问题
- 错误:仅在Controller层使用@CrossOrigin
- 解决方案:在SecurityConfig中配置全局跨域
- Cookie跨域问题
- 错误:使用通配符*时尝试携带Cookie
- 解决方案:指定具体前端地址
- 预检请求处理
- 错误:未放行OPTIONS请求
- 解决方案:添加
requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
- 无状态会话配置
- 错误:未配置无状态会话
- 解决方案:添加
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
五、验证配置是否生效
使用浏览器开发者工具:
- 按F12 → Network标签
- 触发请求 → 查看Response Headers
- 确认存在
Access-Control-Allow-Origin: http://localhost:3000
六、总结
核心问题:浏览器因安全机制拦截跨域请求,需后端明确授权
解决方案:
- 后端配置跨域(Spring Security项目需特别注意)
- 前端代理是临时方案
- 重点检查:放行OPTIONS请求、配置正确前端源、开启无状态会话
注意:确保启动类扫描到SecurityConfig所在包

上面的启动类要指定扫描你的SecurityConfig类所在包"com.exam.config"
- 默认扫描行为 :未显式指定 @ComponentScan 时,Spring Boot会扫描 启动类所在包及其所有子包 (即 com.exam 及其所有子包,包括 com.exam.config )。
- 显式扫描覆盖 :添加显式 @ComponentScan(basePackages=...) 后,默认扫描范围被完全覆盖,Spring仅扫描 指定的包路径 ,不会自动包含启动类所在包的子包。
- 配置失效原因 :
- 移除 "com.exam.config" 后,您自定义的 SecurityConfig.java (位于 com.exam.config 包)未被Spring容器加载
- Spring使用了默认的 WebSecurityConfiguration 和 defaultSecurityFilterChain
- 默认配置没有您自定义的CORS设置( CorsConfigurationSource ),导致跨域请求被拦截
- 默认配置启用了表单登录,将POST请求重定向至GET /login,进一步导致跨域请求失败
239

被折叠的 条评论
为什么被折叠?



