服务器端跨域配置步骤,从原理到实践
服务器端配置跨域请求的核心是设置CORS响应头,通过指定允许的源、方法和头信息,浏览器才会放行跨域请求。 跨域问题是浏览器同源策略的产物,服务器端不主动放开,前端无法通过任何手段绕过,理解这一点,你就能抓住配置的本质。
理解CORS机制是前提
CORS全称跨域资源共享,它通过一组HTTP头让服务器声明哪些跨域请求被允许,浏览器在发起跨域请求时,会先判断是否属于简单请求,如果不是,则先发送一个OPTIONS预检请求,拿到服务器支持的来源、方法、头信息后,才发起实际请求,你需要在服务器端正确响应这个预检请求。
- 简单请求:GET、HEAD、POST,且Content-Type为application/x-www-form-urlencoded、multipart/form-data或text/plain,浏览器直接发送请求,并在响应里检查Access-Control-Allow-Origin头。
- 预检请求:所有其他请求,浏览器先发OPTIONS,服务器返回允许的跨域规则,浏览器再发实际请求。
服务器端跨域配置的具体步骤
无论你使用哪种服务器语言或环境,配置逻辑高度一致,核心是拦截所有请求,设置响应头。
- 判断请求来源,根据业务需求决定是否允许,生产环境不要直接使用,除非是公开API。
- 设置
Access-Control-Allow-Origin为请求的Origin(或允许的特定域名)。 - 设置
Access-Control-Allow-Methods为支持的HTTP方法,如GET, POST, PUT, DELETE, OPTIONS。 - 设置
Access-Control-Allow-Headers为客户端可能携带的自定义头,如Authorization, Content-Type。 - 设置
Access-Control-Max-Age缓存预检结果,避免重复预检。 - 处理预检请求直接返回200,不再进行后续业务逻辑。
- 如果需要携带cookie,设置
Access-Control-Allow-Credentials: true,同时Origin不能是。
关键点: 预检请求的OPTIONS响应必须包含上述头,且状态码为200,很多配置失败都因为忽略了OPTIONS的处理。
跨域请求CORS配置实战:Nginx与Spring Boot
不同服务器环境的配置方式差异较大,但核心逻辑一致,以下给出两种最常用环境的配置示例,你可以直接套用。
Nginx配置跨域请求
Nginx作为反向代理,常在全局或location块中配置跨域头,以下是一个完整的配置片段,支持任意来源的简单请求和预检请求。
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin ;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Headers 'Authorization, Content-Type, X-Requested-With';
add_header Access-Control-Max-Age 86400;
add_header Content-Length 0;
return 200;
}
add_header Access-Control-Allow-Origin ;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Headers 'Authorization, Content-Type, X-Requested-With';
# ... 其他配置
}
- 注意:
if语句在Nginx中性能损耗低,但不要滥用,生产环境建议将跨域配置单独提取到map或server块。 - 多域名场景:使用
map变量动态设置Access-Control-Allow-Origin,只允许白名单域名。
Spring Boot跨域配置
Spring Boot开发中,推荐使用WebMvcConfigurer全局配置,避免在每个Controller重复注解。
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/")
.allowedOriginPatterns("") // 生产环境替换为具体域名
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("")
.allowCredentials(true)
.maxAge(3600);
}
}
- 使用
allowedOriginPatterns可以支持域名通配,比allowedOrigins更灵活。 - 如果使用Spring Security,需要额外配置CORS过滤器,确保跨域头在安全过滤器之前添加。
其他环境简要说明
- Node.js Express:使用
cors中间件,一行代码,支持自定义options。app.use(cors())
- Apache:通过
mod_headers在.htaccess或虚拟主机中添加Header set Access-Control-Allow-Origin,并处理OPTIONS请求。 - IIS:使用URL Rewrite模块或
web.config添加响应头。
跨域请求问题排查:从报错到修复
配置完跨域,浏览器依然报错是常见情况,掌握排查方法比配置本身更重要。
浏览器报错信息解读
浏览器控制台会明确提示跨域失败原因,
No 'Access-Control-Allow-Origin' header is present:服务器未返回该头,或返回的内容与请求源不匹配。Response to preflight request doesn't pass access control check:预检请求响应中缺少必要的头,或状态码不是200,或返回的Allow-Methods不包含实际请求方法。
排查步骤:
- 打开浏览器开发者工具,查看网络请求,找到跨域请求及其OPTIONS预检请求。
- 检查OPTIONS请求的响应头,确认是否包含
Access-Control-Allow-Origin、Allow-Methods、Allow-Headers。 - 确认实际请求的响应头是否包含
Access-Control-Allow-Origin,如果预检通过但实际请求失败,说明实际请求的响应头没有设置正确。 - 如果使用
allowCredentials,确保Access-Control-Allow-Origin不是,而是明确指定的域名。
多域名场景配置实践
当应用需要支持多个来源时,不能简单使用,因为与allowCredentials冲突,推荐做法:
- 在服务器端维护一个白名单列表,读取请求的
Origin头,如果匹配则动态设置Access-Control-Allow-Origin为该来源。 - 在Nginx中,使用
map指令实现;在Spring Boot中,自定义CorsConfiguration并设置allowedOrigins列表。
关于凭证携带
如果需要跨域携带cookie(如基于session的认证),必须同时满足三点:
- 服务端设置
Access-Control-Allow-Credentials: true。 - 服务端
不能是,必须是具体域名。Access-Control-Allow-Origin
- 客户端请求(如fetch)必须设置
credentials: 'include'。
跨域配置后的优化与安全建议
跨域配置不是一次性工作,上线后仍需关注以下细节。
- 合理设置缓存时长:
Access-Control-Max-Age建议设置为一天(86400秒),减少预检请求数量,提升性能。 - 避免暴露过多头信息:
Access-Control-Expose-Headers控制客户端可以读取的响应头,只暴露必要的头。 - 定期审计白名单:随着业务扩展,及时清理不再需要的跨域来源,防止被恶意站点利用。
- 使用代理方案作为备选:在开发环境,前端可以通过webpack-dev-server的proxy配置,将跨域请求转发到后端,绕过浏览器的跨域限制,但生产环境仍需服务器端CORS配置。
跨域配置常见问题解答
Q1: 跨域请求配置后,部分接口仍然被浏览器拦截,原因有哪些?
A: 检查预检请求是否被正确处理,OPTIONS请求必须返回200且包含所需的跨域头,确认实际请求的响应头也包含了跨域头,尤其是当后端框架对不同路径有不同处理时,如果使用了allowCredentials,检查Access-Control-Allow-Origin是否指定了具体的源。
Q2: 服务器端配置跨域请求时,Access-Control-Allow-Origin设置为`是否安全? A: 不安全。允许任何来源访问,如果API包含用户敏感数据或需要认证,则存在安全风险,建议仅对公开的、无认证的API使用,其余情况明确指定允许的域名,并配合Access-Control-Allow-Credentials: true时不能使用`。
Q3: 前后端分离项目中,跨域配置是前端处理还是后端处理?
A: 跨域配置必须由服务器端处理,因为CORS响应头是服务器在HTTP响应中设置的,前端无法通过JavaScript添加这些头,前端可以通过代理方式(如webpack)在开发环境绕过跨域,但在生产环境,服务器端配置是唯一可靠的方式。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/544932.html



