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

在技术层面,前后端分离指在同一个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

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

  1. 如何用Nginx解决跨域问题

    一. 产生跨域的原因 1.浏览器限制 2.跨域 3.XHR(XMLHttpRequest)请求 二. 解决思路 解决跨域有多重,在这里主要讲用nginx解决跨域 1.JSONP 2.nginx代理 3 ...

  2. nginx解决跨域(前后端分离)

    Nginx解决跨域问题 后端接口 请求地址 返回数据(json数据) http://127.0.0.1:8080//app Hello World! 前端代码 通过nginx做静态资源服务器访问端口8 ...

  3. Nginx解决跨域问题(CORS)

    跨域 解决跨域问题一般有两种思路: CORS 在后端服务器设置 HTTP 响应头,把你需要运行访问的域名加入加入 Access-Control-Allow-Origin中. jsonp 把后端根据请求 ...

  4. 使用nginx解决跨域问题(flask为例)

    背景 我们单位的架构是在api和js之间架构一个中间层(python编写),以实现后端渲染,登录状态判定,跨域转发api等功能.但是这样一个中间会使前端工程师的工作量乘上两倍,原本js可以直接ajax ...

  5. 利用nginx解决跨域问题

    访问我的博客 前言 最近遇到了跨域问题,结合之前[微信支付开发本地接收异步通知回调]的经验,利用 Nginx 实现了跨域. 公司之前为了解决跨域问题,用的是 iFrame,反正对于只做后端的我而言,觉 ...

  6. 前端如何使用proxyTable和nginx解决跨域问题

    最近经常遇到跨域的问题,有时候问题虽然解决了,但是还是会有些模棱两可概念不清,于是在网上看了一些教程结合实际使用,做个笔记. 1.跨域原因 浏览器的限制 跨域(协议/域名/端口的不同) XMLHttp ...

  7. vue项目打包本地后通过nginx解决跨域

    前言 有时候我们打包好vue项目让后端人员部署项目时可能会有小插曲,为了不麻烦后端人员和避免尴尬,最好的办法就是在本地自己先测一下,而在本地运行打包后的项目会遇到接口跨域的问题.我平时经常用的方法就是 ...

  8. Nginx解决跨域问题No 'Access-Control-Allow-Origin'

    使用nginx在server块下的location块下为请求添加请求头来解决跨域 add_header 'Access-Control-Allow-Origin' '*'; add_header 'A ...

  9. 通过设置chrome浏览器解决跨域问题,在本地进行开发工作

    后端跨域权限无法打开,于是去网上找了下我这边能不能解决 现在的浏览器出于安全策略的限制,都是不允许跨域的,但是开发的时候经常需要一些别的域的接口,特别是一些接口不是自己能控制的时候,往往会造成开发困难 ...

随机推荐

  1. jfinal极速开发

    下载jfinal项目,上面都配置好了不用自己新建从头配置.https://jfinal.com/ idea打开项目 配置数据库 resources目录下demo-config-dev.txt # co ...

  2. springcloud + nacos实现共用基础服务(灰度版本)

    背景: 当我们使用微服务时,若想在本地联调就需要启动多个服务,为了避免本地启动过多服务,现将注册中心等基础服务共用.当我们在服务A开发时,都是注册到同一个nacos,这样本地和开发环境的服务A就会同时 ...

  3. go thrift 开发

    thrift 从 0.9.1版本开始,可以完美支持 go 语言,可以完美的实现跨语言的 rpc 调用了.下面以 go 和 java 语言相互调用为例. 编辑协议文件,go 语言示例 /** examp ...

  4. zabbix的web界面访问失败问题排查

    现象:用curl访问显示拒绝链接,查看zabbix-server日志也无异常 1.检查防火墙,SElinux是否关闭 2.检查zabbix-server服务是否启动 3.检查80端口是否被占用,比方是 ...

  5. mybatis xml 中 trim 多余的符号

    <if test="(mac != null and mac != '') or (roomNo != null and roomNo != '') or (bedNo != null ...

  6. 141_Power Query之获取钉钉审批流自动刷新Power BI报告

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 钉钉办公给很多企业带来了很多方便,比如审批流线上化,通用化.线上化填写后,数据自动获取又是一个硬伤了,虽然数据可 ...

  7. k8s client-go源码分析 informer源码分析(4)-DeltaFIFO源码分析

    client-go之DeltaFIFO源码分析 1.DeltaFIFO概述 先从名字上来看,DeltaFIFO,首先它是一个FIFO,也就是一个先进先出的队列,而Delta代表变化的资源对象,其包含资 ...

  8. singlelinklist

    C++实现单链表 阅读先知 链表是一种动态数据结构,他的特点是用一组任意的存储单元(可以是连续的,也可以是不连续的)存放数据元素. 链表中每一个元素成为"结点",每一个结点都是由数 ...

  9. Kubernetes client-go 源码分析 - ListWatcher

    概述ListWatch 对象的创建GetterListWatchList() & Watch() 概述 源码版本信息 Project: kubernetes Branch: master La ...

  10. 从零开始构建并编写神经网络---Keras【学习笔记】[1/2]

    Keras简介:   Keras是由纯python编写的基于theano/tensorflow的深度学习框架.   Keras是一个高层神经网络API,支持快速实验,能够把你的idea迅速转换为结果, ...