跨域解决方案推荐
背景
跨域问题对于前端来说,是一个老生常谈的问题了,无论是平时工作中,以及面试中基本都会问到。本文将梳理常见的几种跨域的优缺点,以及建议的跨域解决方案。
基础
什么是跨域?跨域有哪些解决方案?等等基础知识,请参考这篇文章,讲的比较细致,这里就不在啰嗦。
https://segmentfault.com/a/1190000011145364
对比
我们在工作中,用的比较多的三种解决方案:
| 方案 | 优点 | 缺点 | 适用场合 |
|---|---|---|---|
| JSONP | 1、使用简单; 2、不需要任何配置; |
1、GET请求; 2、数据不安全,任何人都可以调用接口; 3、存在XSS攻击; |
1、安全系数要求低; 2、临时使用的接口; 3、应急接口解决方案; |
| CORS | 1、相对安全,但是如果后台配置 Access-Control-Allow-Origin = * 就不那么安全了;2、后台或者Nginx需要配置,如果需要携带Cookie,则前端Ajax也需要配置参数; |
1、需要配置跨域的相关参数,比较麻烦; 2、如果跨域的 Origin 配置为 * , 不安全 |
1、运行环境可以自主灵活配置; 2、跨域只能代码层面处理理; |
| PROXY代理 | 1、非常安全,同域请求; 2、前后端代码不需要任何配置 |
1、对运行环境要求较高,需要配置代理; 2、开发时也需要配置代理才能连调接口 |
1、运行环境可以自主灵活配置; 2、安全系数要求比较高; |
PROXY 代理,就是通过代理软件或者Nginx将地址进行转发,以达到请求接口的地址在同一个域的目的。
JSONP
最主要的缺点就是 不安全,所以公司里面建议不要使用!
CORS
CORS,在公司里面用的比较多,对于CORS的服务端配置,一般有以下两种方式:
- 在后台代码里统一拦截处理reponseHeader,设置CORS协议头;
- 在Nginx配置中,统一拦截返回response,设置CORS协议头;
这两种方案,第一种不需要依赖外部环境,纯粹在代码层面就可以解决问题。对于第二种方案,就比较依赖外部环境。那么,一般这两种方案如何选择呢?我个人给如下建议:
-
推荐如果代码层面分层合理,建议直接在代码层面设置拦截器,统一拦截处理CORS。这么做的好处就是,一套代码无论以后部署在哪里都可以,不需要对外部环境提太多要求,自身系统健壮性比较强。另外,在代码层面处理CORS还有个好处,就是在开发连调、测试阶段,也依然可以方便进行。不然如果太依赖外部环境的话,开发连调环节,也需要搭建一套环境做为中间转发,比较麻烦。 -
不推荐当然,也有人在Nginx中配置CORS,这么做的话,对代码的要求就降低了,不需要考虑跨域问题,但就是多了一个中间环节,无论在开发、测试还是线上,都需要这个中间层,这一点不是很方便。所以,如果是用CORS,不建议使用Nginx配置。
实际项目中,使用CORS典型的场景:H5代码部署在CDN,而后台部署在某后台服务器上。
这种场景下,典型的CDN的环境很难自由配置,而又必须依赖后台接口数据,这时候最好的 办法就是后台代码开发时,就支持跨域。
PROXY代理
PROXY代理 的方法就是通过代理层做一次中间的转发,使得对于浏览器来说,就不存在跨域的问题。
这种方式最大的好处就是绝对安全,不会由于跨域引来一些安全风险,但是缺点就是中间需要做一层代理转发。
实际项目中,使用PROXY代理典型的场景:给客户或者用户使用的后台系统,原因主要在于:
- 对外的一些后台系统,对于安全性和稳定性要求较高;
- 同时,管理后台对于Cookie等状态依赖比较强;
- 后台的一些特殊组件,比如上传组件,有时候对于跨域是比较敏感,所以最好是不跨域,一劳永逸;
如果采用这种方式,那在开发和测试阶段,分别怎么做呢?
本地开发连调
本地 + MockServer
前端代码不需任何配置,只需要MockServer配置 CORS 支持跨域请求就可以。
本地 + 他人机器Server
本地需要安装代理软件,如:Charles
假设,上线后真实的访问路径和接口为:
- 前端页面地址:http://abcd.vivo.com.cn
- 后台接口地址:http://abcd.vivo.com.cn/api
假设,本地和他人机器Server真实的服务地址为:
- 前端页面服务:http://localhost:8080 (本地的Node服务)
- 后台接口地址:http://172.25.122.86:8888 (他人的Tomcat后台服务)
这时候需要配置 Charles 路由 Map Remote规则:

注意:后台接口的路由规则一定要放在前面,即:/api/* 的路由放在页面。
配置好上面的代理后,地址栏直接访问:http://abcd.vivo.com.cn 即可。
生产环境Nginx配置
我们在本地是通过代理软件转发,而测试或者生产环境,则直接通过Nginx的规则,就可以将上述的路由规则做转发,达到同样的目的。
配置 nginx.conf 文件:
server {
listen 80;
server_name abcd.vivo.com.cn;
location / {
proxy_pass http://172.25.122.85:3000;
}
location ~ /api/ {
proxy_pass http://172.25.122.86:8080;
}
}
上述配置可以理解为:
- 监听80端口,将
http://abcd.vivo.com.cn的所有请求服务转发到172.25.122.85:3000; - 将
http://abcd.vivo.com.cn/api/或者http://abcd.vivo.com.cn/api/list等请求转发到http://172.25.122.86:8080
总结
本文主要对比了3种常见的解决跨域的方案,同时重点介绍了 CORS 和 PROXY代理的一些优缺点,以及最适合的场景,归纳总结一下,就是:
- JSONP,能不用就不用,完全不推荐;
- CORS,最适合用于部署在CDN上面的项目,比如:H5项目;
- PROXY代理,最合适管理后台,比如:对外的给客户或者用的管理系统;
(全文完)