跨域

95 阅读3分钟

跨越问题

产生跨域的前提

  • 不同域名:当页面的域名与请求的资源的域名不一致时
  • 不同协议:页面使用https协议加载,但请求是非https资源
  • 不同端口:页面加载是test.com:3000,请求资源是test.com:4000
  • 不同子域名:例如:test.com和test1.com

解决跨域的方法

  • 跨域资源共享(CORS):在服务端设置响应头允许跨域请求
    • 服务端设置响应头中的Access-Control-Allow-Origin字段允许访问的域名,或使用通配符*允许所有域名访问
  • JSONP:动态创建script标签实现跨域请求。服务端返回的数据包装在一个函数调用中,该函数名由客户端制定(缺陷:只支持get请求)
  • 代理服务器:设置一个位于同一域的代理服务器,将跨域请求代理到目标服务器,并将响应返回给客户端。这个方法需要服务器端的额外配置。
  • 跨文档消息传递: 使用window.postMessage()方法,可以在不同窗口或iframe之间进行跨域通信
  • WebSocket:WebSocket是一种双向通信协议,不受同源策略的限制。通过WebSocket,客户端和服务器可以建立持久连接进行跨域通信。
  • Nginx反向代理:使用 Nginx 或其他反向代理服务器可以将跨域请求转发到目标服务器,同时解决跨域问题。这种方法适用于前端无法直接控制目标服务器的情况。

项目背景

测试环境无问题,线上环境某个CSS资源跨域。

项目背景分析

检查后发现浏览器中CSS资源的返回头中缺少CORS头信息,但是在源站OSS存储桶配置了允许跨域头返回头中应该是会携带的。而且别的文件(html\css)返回头中都携带了允许跨域。

问题深层分析

排除浏览器缓存、代码以及浏览器本身的问题,还有砍断资源链路(CDN)配置,网关日志,都没有问题。

借助工具复现

因为测试环境、预发布环境都没有问题,正式环境有问题,不能在正式环境做测试,修改。所以用到谷歌浏览器插件:GoRes。经过多次代理调试,怀疑是CDN缓存导致的(客户端第一次请求CDN时没有携带Origin请求头,CDN就不会将Origin请求头传递到OSS存储桶中,OSS不会响应跨域头,CDN就没有把跨域头的资源内容缓存下来)

解决方法

在这个资源地址后面拼接了参数,相当于请求新的CDN资源地址。此时跨域头就添加上了

跨域资源共享方案

OSS存储桶配置跨域

OSS(对象存储服务)是阿里云提供的云存储服务,可以设置跨域处理,让客户端前端应用从其他域名请求资源

网关服务器配置跨域

网关服务器配置Nginx反向代理服务器。通过配置Nginx location,实现对特定域名的允许跨域支持 实现步骤:

  • 1:修改nginx配置文件(位于/etc/nginx/nginx.conf),添加CORS 配置
  • 2:配置Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers等头信息。
location / {
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE';
    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}

CDN配置跨域

腾讯云CDN有专门针对跨域设置的勾选项,只需要选中保存就行。