跨域是浏览器同源策略下的安全限制当页面与请求地址的协议、域名或端口任意一个不同浏览器会拦截AJAX/Fetch 等请求的响应数据除非服务器通过 CORS 响应头明确放行。1 跨域请求什么是跨域一个 URL 的“源”由三部分组成协议 域名 端口。三者必须完全一致才算同源。不同源就是跨域页面地址请求地址是否跨域原因http://www.test.comhttp://www.test.com/api否同源http://www.test.comhttps://www.test.com/api是协议不同http://www.test.comhttp://api.test.com/api是域名不同http://www.test.com:8080http://www.test.com:3000/api是端口不同http://localhost:3000http://127.0.0.1:3000/api是域名不同2 跨域问题处理2.1 nginx代理使用nginx部署为同一个域2.2 配置当此请求允许跨域2.2.1 跨域返回头需要携带信息响应头是否必须含义示例Access-Control-Allow-Origin必须允许哪些源访问该资源必须包含预检请求中Origin的值https://www.example.comAccess-Control-Allow-Methods必须允许真实请求使用哪些 HTTP 方法GET, POST, PUT, DELETEAccess-Control-Allow-Headers视情况当预检请求携带Access-Control-Request-Headers时必须返回表示允许真实请求携带哪些请求头Content-Type, AuthorizationAccess-Control-Allow-Credentials可选是否允许真实请求携带 Cookie、HTTP 认证等凭证设为true时Allow-Origin不能是*trueAccess-Control-Max-Age可选预检结果缓存多少秒有效期内相同请求不再重复发 OPTIONS864002.2.2 gateway 网关统一处理跨域springboot有处理跨域功能只需要向容器中注入CorsWebFilter对象即可。importorg.springframework.web.cors.reactive.CorsWebFilter;ConfigurationpublicclassGulimallCorsConfigurantion{BeanpublicCorsWebFiltercorsWebFilter(){UrlBasedCorsConfigurationSourcesourcenewUrlBasedCorsConfigurationSource();CorsConfigurationcorsConfigurationnewCorsConfiguration();//允许所有请求头跨域corsConfiguration.addAllowedHeader(*);//允许所有请求方式跨域corsConfiguration.addAllowedMethod(*);//允许所有源跨域corsConfiguration.addAllowedOrigin(*);// 允许真实请求携带 Cookie、HTTP 认证等凭证corsConfiguration.setAllowCredentials(true);source.registerCorsConfiguration(/**,corsConfiguration);returnnewCorsWebFilter(source);}}2.2.3 传统MVC项目处理跨域ConfigurationpublicclassCorsConfigimplementsWebMvcConfigurer{OverridepublicvoidaddCorsMappings(CorsRegistryregistry){registry.addMapping(/**)// 允许所有路径.allowedOriginPatterns(*)// ⚠️ 注意允许携带凭证时必须用 allowedOriginPatterns不能用 allowedOrigins.allowCredentials(true)// 允许携带 Cookie/凭证.allowedMethods(GET,POST,PUT,DELETE,OPTIONS)// 允许的请求方法.allowedHeaders(*)// 允许的请求头.maxAge(3600);// 预检请求缓存时间秒}}3 简单和非简单请求区别简单请求和非简单请求是浏览器 CORS 机制对跨域请求的两种分类区别在于是否触发 OPTIONS 预检请求简单请求直接发送一次非简单请求需要先发预检请求确认权限后再发实际请求。3.1 请求方式区别必须同时满足以下条件请求方法只能是 GET、HEAD、POST请求头只能包含浏览器自动设置的字段如 Accept、Accept-Language、Content-Language、Last-Event-IDContent-Type只能是以下三种之一a. text/plainb. application/x-www-form-urlencodedc. multipart/form-data满足以上全部条件时浏览器直接发出请求不会触发预检。服务器只需在响应头中返回 Access-Control-Allow-Origin浏览器据此决定是否放行。3.2 后端处理对比简单请求非简单请求请求次数1 次2 次OPTIONS 实际请求预检无有后端需额外配置只需Allow-Origin还需Allow-Methods、Allow-Headers实际请求是否到达后端是预检失败则不会到达3.3 简单请求跨域浏览器发现这是跨域请求但属于简单请求浏览器直接发送 GET 请求自动带上 Origin 头 GET /api HTTP/1.1 Origin: http://localhost:3000请求到达后端后端正常处理业务逻辑后端返回响应时在响应头中加上 CORS 头 HTTP/1.1 200 OK Access-Control-Allow-Origin: http://localhost:3000 {“data”:“hello”}浏览器收到响应检查 ACAO 头 → 匹配成功 → 把数据交给前端 JS ✅ → 没有这个头 → 拦截响应JS 拿不到数据 ❌3.4 非简单请求跨域第 1 次浏览器自动发送 OPTIONS 预检请求 OPTIONS /api HTTP/1.1 Origin:http://localhost:3000 Access-Control-Request-Method: POSTAccess-Control-Request-Headers: Content-Type, Authorization第 2 次预检通过后浏览器才发送真正的 POST 请求 POST /api HTTP/1.1 Origin:http://localhost:3000 Authorization: Bearer xxx Content-Type:application/json {“name”: “test”}