写点什么

无需 CORS,用 nginx 解决跨域问题,轻松实现低代码开发的前后端分离

  • 2022 年 7 月 15 日
  • 本文字数:2353 字

    阅读完需:约 8 分钟

无需CORS,用nginx解决跨域问题,轻松实现低代码开发的前后端分离

近年来,前后端分离已经成为中大型软件项目开发的最佳实践。


在技术层面,前后端分离指在同一个 Web 系统中,前端服务器和后端服务器采用不同的技术栈,利用标准的 WebAPI 完成协同工作。这种前后端分离的"混合开发"模式下,前后端通常会部署到不同的服务器上,即便部署在同一台机器,因为宿主程序(如后端用 Tomcat,前端用 nginx)不同,端口号也很难统一。



(图片来源网络)


这意味着位于 A 域(如https://foo:80/website) 的页面,需要调用 B 域的 WebAPI(如https://bar:8080/webservice),这是一个典型的跨域访问,浏览器默认会判定该操作有安全风险。如果不进行处理,则会拒绝这次 WebAPI 调用,提示对应的错误。



(跨域请求导致的错误)


现在如何该怎么解决跨域的问题呢?目前有 4 个主流技术方案:

JSONP

如果你需要处理的请求只有 GET,可以考虑 JSONP。


JSONP 的原理就是利用 <script>标签没有跨域限制的特点,通过 <script>标签 src 属性,发送带有 callback 参数的 GET 请求,服务端将接口返回数据拼凑到 callback 函数中,返回给浏览器,浏览器解析执行,从而前端拿到 callback 函数返回的数据。



(JSONP 的调用流程)


这种做法很常规,但是你需要为前端提供 JSONP 的响应,其他终端调用时提供不带 JSONP 的响应,因此会带来额外的开发和测试工作量。

iFrame

通常情况下,前后端分离带来的跨域访问都局限在同一个主域的不同子域(如 a.foo.com 和 b.foo.com)之间。所以,你可以利用 iFrame 加载位于被调用 WebAPI 所在域的页面,然后将两个页面的 document.domain 设置为主域名(如 foo.com),就通过 iFrame 中的子页面请求 WebAPI 了。



(图片来源网络)


这种做法比较麻烦,我们需要为 WebAPI 配套开发起中转作用的页面,但对于开发者而言依旧有很大的开发工作量。

CORS

和前两种方案相比,CORS(跨域资源共享)是一个"一劳永逸"的方案。


我们不需要为每个 WebAPI 做额外的处理,而是需要在后端程序启动时,增加一些处理工作。主流的后端服务都有处理 CORS 的类库,这里就不再做展开介绍了。


这个方案的核心原理,是在发起正式的请求前,先发送一个 OPTIONS 谓词的 HTTP 请求,询问发起请求的页面是否有调用该域服务的权限;如果后端说 OK,浏览器就继续请求,否则提示错误。


使用这种方案的开发工作量小,如果直接使用成熟类库的话,开发和测试的工作量甚至可以忽略不计。不过,因为每个跨域的请求都会触发一次往外的 OPTIONS 请求,对服务器会造成额外的开销和压力。

反向代理

反向代理机制,把前端的 A 域和后端的 B 域合并成一个 C 域,从根本上解决跨域问题。


这个方案仅需配置,对前后端的程序没有侵入;同时内网中的反向代理通常也不会带来额外的性能开销。



(图片来源网络)


总体来说在编码开发的时代,上述四种方案都有适用的应用场景,各有优缺点。进入低代码开发时代后,前后端分离的应用面更广,如使用 JavaScript 编码开发前端、配合低代码构建的后端,或使用 Java 编码开发后端,供低代码构建的前端调用。



(低代码时代的前后端分离,来自 低代码沙龙)


低代码开发的核心价值在于节省开发投入,提升开发效率,所以,方案 1(JSONP)和方案 2(iFrame)已经很少被用到低代码混合开发领域。相比于方案 3(CORS),方案 4(反向代理)因为性能开销较小,应用场景会更多一些。


下面,我们将以活字格+nginx 为例,介绍利用 nginx 解决跨域问题,实现前后端分离的具体做法。



(反向代理的架构示意图)

利用 nginx 解决跨域问题

  1. 开始配置之前,我们使用活字格开发两个应用,仅包含前端页面的 frontend 和包含后端 WebAPI(服务端命令)的 backend,并将其分别发布到物理机或云主机上,应用的端口设置为 8081 和 8080。我们可以通过以下地址访问这两个应用:



  1. 安装 nginx,并在配置文件/conf/nginx.conf 中 HTTP 节点配置前后端的服务器,即 upstream 节点:



upstream backend {
server host\_name:8080;
}
upstream frontend {
server host\_name\_2:8081;
}
复制代码


  1. 在 HTTP 节点下的 server 节点,配置监听端口和转发策略,这样就可以将 http://host_name:8080/backend 映射为 http://proxy_name:8000/backend ,http://host_name_2:8081/frontend 映射为http://proxy_name:8000/frontend



listen 8000;
server\_name proxy\_name;
location /frontend {
proxy\_pass http://frontend/frontend ;
}
location /backend {
proxy\_pass http://backend/backend ;
}
复制代码


  1. 上述操作后,用户访问的域名统一成了http://proxy_name:8000,跨域问题解决了。但是,不要着急。活字格默认会启用 Http Referer 验证机制,不允许跨域调用内置服务。所以,你还需要打开前端应用所在的服务端的管理控制台http://host_name_2:22345/UserService/ManagementPage/WebSecurity


在 HTTP Referrer 允许列表中添加 nginx 代理服务器的地址(也就是用户实际使用的地址,记得在后面加一个*号适配)。



  1. 配置完成后,你可以就可以在前端页面中通过【发送 HTTP 请求命令】,调用后端的 WebAPI 了。



(在前端调用后端 WebAPI 并弹窗显示返回结果)


特别提示:如果你需要将前端、后端和 nginx 部署在同一台机器上,可以将上述 proxy_name、host_name、host_name_2 统一替换为你的机器名或 IP 地址。


作为一款强大的反向代理和 Web 服务器,nginx 的用途非常广泛,本文仅仅使用到了它的反向代理功能。除此之外对于负载均衡的解决 nginx 也有很优秀的表现,在后续内容中我们会为大家做更加深入的介绍。


如需详细了解如何使用低代码开发前后端分离的企业级应用,快速转型全栈工程师,可以查看:


https://gcdn.grapecity.com.cn/forum.php?mod=viewthread&tid=146511&extra=page%3D1%26filter%3Dtypeid%26typeid%3D272


除此之外如果你对更多低代码行业现状与发展趋势感兴趣可以查看:


https://help.grapecity.com.cn/pages/viewpage.action?pageId=67969931

发布于: 刚刚阅读数: 5
用户头像

赋能开发者 2020.05.09 加入

西安葡萄城信息技术有限公司是全球领先的软件开发技术和 低代码 平台提供商,以“ 赋能开发者”为使命,致力于通过各类软件开发工具和服务,创新开发模式,提升开发效率,推动软件产业发展,为“数字中国”建设提速

评论

发布
暂无评论
无需CORS,用nginx解决跨域问题,轻松实现低代码开发的前后端分离_nginx_葡萄城技术团队_InfoQ写作社区