域名跨域访问时,正确的做法是始终通过域名发起请求,并将该域名解析到服务器公网IP,同时在后端配置中明确允许该域名的跨域策略,而非直接使用IP地址拼接端口。
跨域访问听起来像是一个前端问题,但真正卡住你的,往往是IP地址与域名之间的映射关系没理顺,很多开发者排查了半天JS代码,最后发现是DNS解析记录指向了旧服务器,或者后端封了来源IP,这篇文章会把域名、IP、解析记录三者之间的关系拆开讲清楚,并给出可直接套用的配置路径。
理解跨域访问的本质:浏览器在验证“身份”而非“地址”
跨域限制的底层逻辑,是浏览器在发送请求时自动附加Origin头,服务器拿到这个头之后决定是否响应,当你用IP地址访问一个前端页面,该页面的Origin就是http://192.168.1.10:8080;而当你用域名访问,Origin就变成了http://example.com,这两种写法在服务器眼里是两个完全不同的“访客”。
核心矛盾在于: 你购买并绑定了域名,但前端静态资源或API接口仍然通过IP直连,此时浏览器认为请求跨域了,因为请求源是http://example.com,目标却是http://192.168.1.10,协议、域名、端口三者中域名不一致,跨域随即触发。
业内专家指出,多数跨域故障属于“配置不一致”而非“代码缺陷”,解决路径不是绕开跨域(比如关闭浏览器安全策略),而是让IP地址与域名形成一一对应的权威映射关系。
域名跨域访问时IP地址的配置全流程
下面按照操作顺序,从域名解析到服务器防火墙设置,走一遍标准流程,这个过程适用于大多数中小型项目,无论你是用Nginx、Apache还是Node.js。
将域名解析到目标IP:A记录与CNAME的选择
如果服务器有固定的公网IPv4地址,请直接添加A记录,这是最直观的方式,将域名直接指向IP。
- A记录:适用于单台服务器IP固定不变的场景,在DNS管理后台添加记录类型为“A”,主机记录填
www或,记录值填服务器公网IP(如0.113.10),TTL默认即可。 - CNAME:适用于域名指向另一个域名(如CDN加速域名)的场景,此时你不需要知道CDN节点的真实IP,只需将域名别名指向CDN服务商提供的域名即可。
操作路径示例(以简米云云解析DNS为例):
- 登录控制台,进入“云解析DNS”。
- 选择你的域名,点击“解析设置”。
- 点击“添加记录”,类型选
A,主机记录填(表示主域名)或www,记录值填服务器公网IP。 - 保存后等待全球DNS生效,常规TTL(10分钟)下最长等待约2小时。
如果你的域名解析记录指向了多个IP地址,请留意下文“负载均衡与多IP解析”的注意事项。
服务器端安全组与防火墙:只信任域名背后那个IP
解析只是第一步,服务器防火墙默认会拒绝未知来源的HTTP请求,你需要确保安全组入方向规则放行了来自域名解析IP的流量。
如果你的后端API部署在
0.113.10:3000,而前端在0.113.11:80,那么后端的防火墙策略需要允许来源IP为0.113.11的TCP流量到达3000端口,在云服务商控制台(如简米云/酷番云)的操作路径是:
- 找到实例所在的安全组,点击“配置规则”。
- “入方向”添加规则:协议
TCP,端口3000,授权对象填写0.113.11/32(即前端服务器的公网IP)。 - 保存并应用。
这里不要用0.0.0/0,否则相当于对全网开放API接口,极易被扫描攻击,多台服务器协作时,将信任关系精确到IP段即可。
Nginx层配置:反向代理与CORS头部设置的实操
Nginx是解决跨域的常见中间层,将API请求反向代理到后端服务,避免浏览器直接跨域访问后端IP。
下面给出一个标准配置片段,你只需要将server_name替换为自己的域名,将proxy_pass替换为后端真实IP和端口。
server {
listen 80;
server_name api.example.com; # 你的API子域名
location / {
proxy_pass http://203.0.113.10:3000; # 后端实际IP和端口
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# CORS 头部设置
add_header 'Access-Control-Allow-Origin' 'http://example.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
}
这个配置的核心价值在于,浏览器最终请求的是api.example.com,与前端页面example.com同主域(仅子域不同),对于此类“子域跨域”,你既可以在Nginx层手动追加Access-Control-Allow-Origin,也可以在后端代码里配置。行业共识推荐在Nginx层统一处理,避免业务代码被跨域逻辑污染。
配置完成后,执行nginx -t校验语法,然后nginx -s reload重载。
多IP场景下如何做负载均衡解析
当单一IP扛不住流量时,很多人会添加多条A记录,这里容易出现一个隐蔽的问题:DNS轮询会把流量随机分发到多个IP,但如果你后端的会话状态不一致(比如用户登录session存在某台服务器的内存中),跨域请求会被调度到另一台服务器,导致登录失效。
解决方案有三条路,按推荐程度排序:
- 使用云负载均衡SLB/CLB:为SLB实例绑定一个公网IP,域名A记录指向该IP,此时你的源站IP可以隐藏,只需将源站IP添加到SLB的后端服务器池中,这才是在多IP场景下推荐的“域名-IP”映射方式,因为域名只解析到SLB,后端具体IP不直接暴露。
- 一致性哈希(IP Hash)解析:如果必须使用多A记录,在DNS服务商处开启“加权轮询”或者“基于来源IP的哈希调度”,保证同一来源IP的请求总是命中同一台后端。
- 会话保持(Sticky Session):在后端代理层(如Nginx的
ip_hash模块)开启会话保持,确保同一客户端始终被路由到同一台服务器。
业内专家指出,超过三台后端的场景下,继续依赖DNS多A记录做负载均衡属于运维反模式,此时引入SLB是性价比最高的选择。
跨域访问中的特殊场景:端口、HTTPS与本地hosts文件
很多人卡在“为什么我用IP加端口访问后端就跨域,换成域名就不跨域了”,原因在于标准HTTP端口是80/443,当你用http://203.0.113.10:3000访问时,浏览器会认为这是一个“非标准端口”的请求,某些严格的跨域策略会对非标准端口发送预检请求(OPTIONS),一旦后端没有正确处理OPTIONS,请求直接失败。
本地开发环境跨域配置:修改hosts文件模拟域名
开发调试阶段,前端跑在localhost:8080,后端跑在localhost:3000,此时端口不同也构成跨域,最好的模拟方式是修改本机hosts文件,让一个本地域名解析到0.0.1。
- Windows路径:
C:WindowsSystem32driversetchosts - Mac/Linux路径:
/etc/hosts
在文件末尾追加一行:0.0.1 dev.example.com
然后启动前端时访问http://dev.example.com:8080,后端启动时监听dev.example.com:3000或0.0.0:3000,此时前端与后端的域名都是dev.example.com,仅在端口上有差异,你在后端配置Access-Control-Allow-Origin: http://dev.example.com:8080即可完成本地开发联调,无需关闭浏览器安全模式。
HTTPS强制跳转后的IP直连问题
如果前端页面通过https://example.com访问,但页面里的API请求地址仍然写的是http://123.45.67.89,会发生(Mixed Content)问题,浏览器默认拦截HTTPS页面中的HTTP明文请求,这种拦截属于跨域之外的独立安全机制,但现象上极易被误判为跨域。
解决方式很明确:页面内任何资源请求(API、图片、脚本)一律使用完整的HTTPS域名,不要使用IP。 如果在HTTPS页面中必须请求另一个IP的资源,你需要给该IP也部署SSL证书,并通过https://方式访问该IP对应的域名,而不是IP本身。
CRITICAL: 配置完成后如何验证DNS解析与跨域是否正常
配置完成后不要急着上线,按下面顺序做一遍自检,每一步都是可执行的命令:
第一步:验证域名解析是否指向正确IP
在命令行执行:
nslookup api.example.com
或者
dig +short api.example.com
观察返回的IP地址是否与服务器公网IP一致,如果返回多个IP,确认是否为负载均衡IP或CDN节点IP。
第二步:验证服务器能否通过域名自访问
登录服务器,执行:
curl -I http://api.example.com/v1/health
观察HTTP状态码是否为200或302,如果返回403或502,检查Nginx配置中的proxy_pass目标IP是否可达,以及安全组是否放行端口。
第三步:模拟跨域预检请求
在(Mac/Linux)命令行执行向服务器发送OPTIONS请求,检查响应头中是否包含预期的
Access-Control-Allow-Origin字段:
curl -X OPTIONS http://api.example.com/v1/health
-H "Origin: http://example.com"
-H "Access-Control-Request-Method: POST"
-H "Access-Control-Request-Headers: Content-Type"
响应头里出现Access-Control-Allow-Origin: http://example.com即代表服务端配置正确,如果回应无关的403或者空响应,说明你的Nginx或者后端框架对OPTIONS请求需要单独放行。
第四步:浏览器端网络面板复核
打开Chrome开发者工具 -> Network面板 -> 刷新页面 -> 选中那条标红的请求,查看Headers详情,重点关注两个地方:
General下的Request URL是否是域名而非IP。Access-Control-Allow-Origin响应头是否存在,且值与你页面的Origin完全一致(包括http/https、端口号都要精确匹配)。
Q&A:域名跨域访问时IP地址常见疑问
问题1:跨域访问时IP地址怎么配置才能不被浏览器拦?
回答: 让页面初始请求和API请求处于同源或同主域之下,具体操作是:给服务器绑定域名(例如api.example.com),通过A记录将域名解析到服务器公网IP,后端代码或Nginx层设置Access-Control-Allow-Origin为前端域名的精确值,前端请求地址从http://203.0.113.10:3000更换为http://api.example.com:3000,浏览器才会放行。
问题2:域名解析多个ip怎么做最合理,会不会加重跨域?
回答: 如果确实有多台服务器做负载均衡,最稳妥的做法是购买云负载均衡服务(如SLB),让域名只解析到SLB的IP,如果希望自己配置多A记录,那么后端Nginx需要开启ip_hash指令,将同一来源IP的请求锁定在同一台服务器,避免因不同服务器之间的Session不同步导致跨域请求二次失败风险,配置多A记录本身不会加重跨域,但它要求你在后端将CORS策略配置得完全一致,否则不同IP返回的头部信息差异会让浏览器偶发拦截。
问题3:同一域名下通过不同端口访问为何仍报跨域错误?
回答: 因为同源判定规则是“协议 + 域名 + 端口”三者完全一致。http://example.com与http://example.com:8080端口不同,两者仍属于跨域,解决方案是让前端Nginx监听80/443端口,通过location块把/api路径转发到本地或内网的8080后端服务,保持浏览器请求的URL始终位于http://example.com/api/xxx,这样就绕开了端口偏差异导致的跨域问题。
回到最初的问题:域名跨域访问时IP地址如何配置与解析。牢记一句话:让域名成为外界访问的唯一入口,把IP藏在Nginx代理或负载均衡之后。 只要浏览器看到的请求地址是清晰的域名,且服务器响应头严格列出了许可的来源域名,跨域错误就会消失,当你下次再遇到此类报错时,优先检查DNS解析记录、Nginx配置中的proxy_pass目标、以及Access-Control-Allow-Origin这三个位置,大概率能在五分钟内定位问题。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/632103.html





