在现代web应用架构中,为了实现业务分离、负载均衡或模块化管理,我们常常会使用子域名。
api.example.com
用于提供API服务,而
www.example.com
作为主站,这种架构会引发一个常见的技术需求:子域名(如
api.example.com
)的前端页面需要调用主域名(如
www.example.com
)上的共享资源、接口或用户会话信息,这种跨域调用是构建统一用户体验的关键。
核心挑战:浏览器的同源策略
要实现子域名调用主域名文件,首先必须理解“同源策略”,这是浏览器一个核心的安全功能,它规定了一个源的文档或脚本,不能读取或修改另一个源的文档属性,所谓“同源”,指的是“协议+域名+端口”三者完全相同。
和
被视为不同源,因为它们的域名不同,浏览器会默认阻止前者通过JavaScript(如或
XMLHttpRequest
)直接请求后者的资源,从而抛出跨域错误,要解决这个问题,我们需要采用特定的技术手段来“合法地”绕过这一限制。
实现跨域调用的主流方案
针对子域名与主域名之间的跨域问题,业界有几种成熟且可靠的解决方案,每种方案都有其适用场景。
CORS(跨域资源共享):现代标准方案
CORS是W3C推荐的标准,也是目前最主流、最安全的跨域解决方案,它通过在HTTP响应中添加特定的头部字段,来告知浏览器哪些跨域请求是被允许的。
实现方式非常直接: 在主域名(被请求方)的服务器上进行配置 。
当子域名的页面发起请求时,浏览器会自动在请求头中附加字段,标明自己的来源,主域名的服务器收到请求后,若判断该来源合法,就在响应头中返回
Access-Control-Allow-Origin
等字段,浏览器检查通过后,就会将响应数据交给JavaScript处理。
关键HTTP响应头配置示例如下:
| HTTP响应头 | 作用 | 示例 |
|---|---|---|
Access-Control-Allow-Origin
|
允许哪些源(域名)访问 |
Access-Control-Allow-Origin:或 (允许所有源,生产环境慎用)
|
Access-Control-Allow-Methods
|
允许哪些HTTP方法 |
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
|
Access-Control-Allow-Headers
|
允许携带哪些自定义请求头 |
Access-Control-Allow-Headers: Content-Type, Authorization
|
Access-Control-Allow-Credentials
|
是否允许发送Cookie(需与
withCredentials
配合)
|
Access-Control-Allow-Credentials: true
|
对于子域名调用主域名这种场景,将
Access-Control-Allow-Origin
设置为具体的子域名地址,是安全且精确的做法。
反向代理:服务器端透明处理
如果无法修改主域名服务器的配置(调用的是第三方服务),或者希望对客户端完全透明地处理跨域问题,反向代理是绝佳选择。
实现思路是在子域名(请求方)的服务器上(如Nginx、Apache)配置一个代理规则,当浏览器请求
时,该服务器并不直接处理,而是将这个请求“转发”给主域名的
,获取响应后,再返回给浏览器。
对于浏览器而言,它始终是在向
api.example.com
发起请求,这是一个同源请求,因此不会触发任何跨域限制,整个跨域过程在服务器内部完成,对前端开发者完全透明。
document.domain
:特定场景下的便捷方法
这是一种较为古老且适用范围有限的方法,它仅适用于
主域相同、子域不同
的场景(如
www.example.com
和
app.example.com
)。
在两个页面的JavaScript中,都设置
document.domain = 'example.com';
,这样,浏览器就会认为它们处于同一个域下,从而允许它们通过或
window.postMessage
等方式进行互相通信和操作,但此方法不支持跨域Ajax请求,且在现代浏览器中逐渐被限制,不推荐在新项目中使用。
方案选择建议
相关问答 (FAQs)
问题1:CORS 和 JSONP 的主要区别是什么?为什么现在更推荐使用 CORS?
解答: CORS和JSONP都是为了解决跨域问题,但原理和特性差异巨大。
问题2:如果我无法修改主域名服务器的配置,子域名还能调用其文件吗?
解答: 可以,这种情况下,最佳解决方案是使用 反向代理 ,你可以在你自己的子域名服务器(使用Nginx)上进行配置,具体操作是,设置一个代理规则,将所有发往子域名特定路径(如)的请求,都转发到主域名的对应地址,这样,浏览器始终是和你的子域名服务器通信,属于同源请求,自然不会产生跨域问题,整个过程在服务器端完成,对前端代码无任何侵入性,也无需获得主域名服务器的权限。














发表评论