Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

跨域解决方案推荐 #50

Open
sunmaobin opened this issue May 2, 2018 · 0 comments

Comments

@sunmaobin
Copy link
Owner

commented May 2, 2018

背景

跨域问题对于前端来说,是一个老生常谈的问题了,无论是平时工作中,以及面试中基本都会问到。本文将梳理常见的几种跨域的优缺点,以及建议的跨域解决方案。

基础

什么是跨域?跨域有哪些解决方案?等等基础知识,请参考这篇文章,讲的比较细致,这里就不在啰嗦。

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的服务端配置,一般有以下两种方式:

  1. 在后台代码里统一拦截处理reponseHeader,设置CORS协议头;
  2. 在Nginx配置中,统一拦截返回response,设置CORS协议头;

这两种方案,第一种不需要依赖外部环境,纯粹在代码层面就可以解决问题。对于第二种方案,就比较依赖外部环境。那么,一般这两种方案如何选择呢?我个人给如下建议:

  • 推荐 如果代码层面分层合理,建议直接在代码层面设置拦截器,统一拦截处理CORS。这么做的好处就是,一套代码无论以后部署在哪里都可以,不需要对外部环境提太多要求,自身系统健壮性比较强。另外,在代码层面处理CORS还有个好处,就是在开发连调、测试阶段,也依然可以方便进行。不然如果太依赖外部环境的话,开发连调环节,也需要搭建一套环境做为中间转发,比较麻烦。
  • 不推荐 当然,也有人在Nginx中配置CORS,这么做的话,对代码的要求就降低了,不需要考虑跨域问题,但就是多了一个中间环节,无论在开发、测试还是线上,都需要这个中间层,这一点不是很方便。所以,如果是用CORS,不建议使用Nginx配置。

实际项目中,使用CORS典型的场景:H5代码部署在CDN,而后台部署在某后台服务器上。

这种场景下,典型的CDN的环境很难自由配置,而又必须依赖后台接口数据,这时候最好的 办法就是后台代码开发时,就支持跨域。

PROXY代理

PROXY代理 的方法就是通过代理层做一次中间的转发,使得对于浏览器来说,就不存在跨域的问题。

这种方式最大的好处就是绝对安全,不会由于跨域引来一些安全风险,但是缺点就是中间需要做一层代理转发。

实际项目中,使用PROXY代理典型的场景:给客户或者用户使用的后台系统,原因主要在于:

  • 对外的一些后台系统,对于安全性和稳定性要求较高;
  • 同时,管理后台对于Cookie等状态依赖比较强;
  • 后台的一些特殊组件,比如上传组件,有时候对于跨域是比较敏感,所以最好是不跨域,一劳永逸;

如果采用这种方式,那在开发和测试阶段,分别怎么做呢?

本地开发连调

本地 + MockServer

前端代码不需任何配置,只需要MockServer配置 CORS 支持跨域请求就可以。

本地 + 他人机器Server

本地需要安装代理软件,如:Charles

假设,上线后真实的访问路径和接口为:

假设,本地和他人机器Server真实的服务地址为:

这时候需要配置 Charles 路由 Map Remote规则:

Imgur

注意:后台接口的路由规则一定要放在前面,即:/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种常见的解决跨域的方案,同时重点介绍了 CORSPROXY代理的一些优缺点,以及最适合的场景,归纳总结一下,就是:

  • JSONP,能不用就不用,完全不推荐;
  • CORS,最适合用于部署在CDN上面的项目,比如:H5项目;
  • PROXY代理,最合适管理后台,比如:对外的给客户或者用的管理系统;

(全文完)

@sunmaobin sunmaobin added this to the 2018年 milestone May 2, 2018

@sunmaobin sunmaobin self-assigned this May 2, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
1 participant
You can’t perform that action at this time.