CORS跨域与Nginx反向代理跨域优劣对比

Posted 程序猿knight

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CORS跨域与Nginx反向代理跨域优劣对比相关的知识,希望对你有一定的参考价值。

最近写了一些关于前后端分离项目之后,跨域相关方案的基本原理和常见误区的帖子,主要包括CORS和nginx反向代理。这两种方案项目中都有在用,各有优缺,关于具体使用哪种方案,大家的观点也不大一致,本文主要就此展开一下,从前后端及服务器配置、安全性、移植灵活性、扩展性等方面详细对比一下两种方案的优缺,以便于后期在方案选型上对大家有所帮助。

先了解一下为什么跨域:

  • 2.服务器解析程序收到浏览器跨域请求后,根据自身配置返回对应文件头。若未配置过任何允许跨域,则文件头里不包含Access-Control-Allow-origin字段,若配置过域名,则返回Access-Control-Allow-origin+ 对应配置规则里的域名的方式。

  • 3.浏览器根据接受到的http文件头里的Access-Control-Allow-origin字段做匹配,若无该字段,说明不允许跨域;若有该字段,则对字段内容和当前域名做比对,如果同源,则说明可以跨域,浏览器发送该请求;若不同源,则说明该域名不可跨域,不发送请求

总结一下跨域的原因就是一句话:不同IP或不同端口就是跨域。

前端配置

CORS方案:跨域时部分浏览器默认不携带cookie,因此为了携带cookie需要设置一下xmlhttprequest的withCrendetails属性,使用vue-resouce时设置如下
Vue.http.options.credentials = true
用axios时,可以在拦截器中设置如下
axios.interceptors.request.use((config) => {
    config.withCredentials = true
    return config
}, (error) => {    return Promise.reject(error)
})
使用原生XMLHttpRequest对象时如下,
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

如果不需要传递cookie,最好置成false,避免不嗯浏览器默认允许cookie的携带。

Nginx反向代理:此时前端相当于不跨域,和正常请求一致,无需额外配置。

后端配置

CORS方案: 后端需要包装ACA系列header,
'Access-Control-Allow-Origin' '*';'Access-Control-Allow-Credentials' "true"; 'Access-Control-Allow-Headers' 'X-Requested-With';

除此以外无需额外配置。

Nginx反向代理:此时后端相当于不跨域,和正常请求一致,无需额外配置。

服务器配置

CORS方案: 无。
Nginx反向代理:该方案跨域工作都集中在nginx服务器上,配置如下
...proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;...location /api {
   proxy_pass https://b.test.com; # 设置代理服务器的协议和地址
   proxy_cookie_domain b.test.com  a.test.com; # 修改cookie,针对requestresponse互相写入cookie}       
...

原理移步nginx反向代理跨域基本配置与常见误区、nginx配置解析之客户端真实IP的传递

安全性

  • CORS方案: 由于此时浏览器会默认添加origin属性,服务端可以直接查到请求来源,便于控制来源、屏蔽黑名单链接。同时服务端域名和端口会暴露出来。

移植灵活性、扩展性

  • CORS方案: 只需要在代码或者配置中心进行黑白名单配置即可,方便移植和扩展。

  • Nginx反向代理:不同环境服务域名可能不一致,因此nginx配置也各不相同,不便于移植。而对于扩展性,当存在新的项目需要访问接口服务器时,需要首先访问nginx中server指定的域名,再由server域名反向代理到接口服务器,比如

server { 
    listen       8443;    server_name  a.test.com;    
    client_max_body_size            100m;        
    ssl ...

    location /micro{        proxy_pass   https://b.test.com;  #反向代理
        proxy_cookie_domain b.test.com a.test.com; #修改cookie
        add_header 'Access-Control-Allow-Origin' 'htps://c.test.com';        add_header 'Access-Control-Allow-Credentials' "true"; 
        add_header Access-Control-Allow-Headers X-Requested-With;
    }
}

这个时候跨域模型就变了,由单纯的a.test.com反向代理到b.test.com,变成了a.test.com反向代理到b.test.com以及c.test.comCORS到a.test.com再反向代理到b.test.comd的情况。这个有点绕,但仔细想一下就会明白。这无疑增加了后期的维护成本。

综合对比

综合以上,我们大致可以得到如下图标

Item CORS Nginx反向代理
代码配置--前端 credentials=true
代码配置--后台 setHeader:ACA-Origin、ACA-Method、ACA-Credentials等
服务器配置 Nginx配置
移植灵活性 高、无需额外配置 低、每套环境配置可能均不相同
安全性 高、来源可控、直接追溯 X-Forwarded-For追溯多级来源
新项目扩展 黑白名单控制 更新配置,跨域模型会产生变化

对比结论

综上呢,对于公共基础服务,由于涉及到对接的前端项目可能比较多,开发测试部署环境也比较多,整体上来讲我更倾向于推荐大家使用CORS方案。而对于一些对立性强的小项目,使用nginx则可以降低你的开发成本,快速发开快速上线。具体使用当然也要结合工作实际,按需使用吧。 此外对于Nginx反向代理方案使用时,推荐使用内部域名/ip作为接口服务器的入口,尽量不要暴露到外面,以免出现不必要的安全问题。

推荐阅读











以上是关于CORS跨域与Nginx反向代理跨域优劣对比的主要内容,如果未能解决你的问题,请参考以下文章

nginx 反向代理 proxy_pass 及对比nginx与haproxy反向代理服务器功能性能的优劣

Node.js实战一文带你开发博客项目之联调(导入HTMLNginx反向代理CORS解决跨域与前端联调)

Node.js实战一文带你开发博客项目之联调(导入HTMLNginx反向代理CORS解决跨域与前端联调)

Nginx的反向代理跨域

Nginx转发+反向代理实现跨域接口转发

Nginx通过CORS实现跨域(转)