




已阅读5页,还剩30页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
前后端分离的思考与实践(一)作者:常胤|时间:2014-04-04 17:20也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离)前言为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异。痛定思痛,今天我们重新思考了“前后端”的定义,引入前端同学都熟悉的NodeJS,试图探索一条全新的前后端分离模式。随着不同终端(Pad/Mobile/PC)的兴起,对开发人员的要求越来越高,纯浏览器端的响应式已经不能满足用户体验的高要求,我们往往需要针对不同的终端开发定制的版本。为了提升开发效率,前后端分离的需求越来越被重视,后端负责业务/数据接口,前端负责展现/交互逻辑,同一份数据接口,我们可以定制开发多个版本。这个话题最近被讨论得比较多,阿里有些BU也在进行一些尝试。讨论了很久之后,我们团队决定探索一套基于NodeJS的前后端分离方案,过程中有一些不断变化的认识以及思考,记录在这里,也希望看到的同学参与讨论,帮我们完善。一、什么是前后端分离?最开始组内讨论的过程中我发现,每个人对前后端分离的理解不一样,为了保证能在同一个频道讨论,先就什么是”前后端分离”达成一致。大家一致认同的前后端分离的例子就是SPA(Single-page application),所有用到的展现数据都是后端通过异步接口(AJAX/JSONP)的方式提供的,前端只管展现。从某种意义上来说,SPA确实做到了前后端分离,但这种方式存在两个问题: WEB服务中,SPA类占的比例很少。很多场景下还有同步/同步+异步混合的模式,SPA不能作为一种通用的解决方案。 现阶段的SPA开发模式,接口通常是按照展现逻辑来提供的,有时候为了提高效率,后端会帮我们处理一些展现逻辑,这就意味着后端还是涉足了View层的工作,不是真正的前后端分离。SPA式的前后端分离,是从物理层做区分(认为只要是客户端的就是前端,服务器端的就是后端),这种分法已经无法满足我们前后端分离的需求,我们认为从职责上划分才能满足目前我们的使用场景: 前端:负责View和Controller层。 后端:只负责Model层,业务处理/数据等。为什么去做这种职责的划分,后面会继续探讨。二、为什么要前后端分离?关于这个问题,玉伯的文章Web研发模式演变中解释得非常全面,我们再大概理一下:2.1 现有开发模式的适用场景玉伯提到的几种开发模式,各有各的适用场景,没有哪一种完全取代另外一种。 比如后端为主的MVC,做一些同步展现的业务效率很高,但是遇到同步异步结合的页面,与后端开发沟通起来就会比较麻烦。 Ajax为主SPA型开发模式,比较适合开发APP类型的场景,但是只适合做APP,因为SEO等问题不好解决,对于很多类型的系统,这种开发方式也过重。2.2 前后端职责不清在业务逻辑复杂的系统里,我们最怕维护前后端混杂在一起的代码,因为没有约束,M-V-C每一层都可能出现别的层的代码,日积月累,完全没有维护性可言。虽然前后端分离没办法完全解决这种问题,但是可以大大缓解。因为从物理层次上保证了你不可能这么做。2.3 开发效率问题淘宝的Web基本上都是基于MVC框架webx,架构决定了前端只能依赖后端。所以我们的开发模式依然是,前端写好静态demo,后端翻译成VM模版,这种模式的问题就不说了,被吐槽了很久。直接基于后端环境开发也很痛苦,配置安装使用都很麻烦。为了解决这个问题,我们发明了各种工具,比如VMarket,但是前端还是要写VM,而且依赖后端数据,效率依然不高。另外,后端也没法摆脱对展现的强关注,从而专心于业务逻辑层的开发。2.4 对前端发挥的局限性能优化如果只在前端做空间非常有限,于是我们经常需要后端合作才能碰撞出火花,但由于后端框架限制,我们很难使用Comet、Bigpipe等技术方案来优化性能。为了解决以上提到的一些问题,我们进行了很多尝试,开发了各种工具,但始终没有太多起色,主要是因为我们只能在后端给我们划分的那一小块空间去发挥。只有真正做到前后端分离,我们才能彻底解决以上问题。三、怎么做前后端分离?怎么做前后端分离,其实第一节中已经有了答案: 前端:负责View和Controller层。 后端:负责Model层,业务处理/数据等。试想一下,如果前端掌握了Controller,我们可以做url design,我们可以根据场景决定在服务端同步渲染,还是根据view层数据输出json数据,我们还可以根据表现层需求很容易的做Bigpipe,Comet,Socket等等,完全是需求决定使用方式。3.1 基于NodeJS“全栈”式开发如果想实现上图的分层,就必然需要一种web服务帮我们实现以前后端做的事情,于是就有了标题提到的“基于NodeJS的全栈式开发”这张图看起来简单而且很好理解,但没尝试过,会有很多疑问。 SPA模式中,后端已供了所需的数据接口,view前端已经可以控制,为什么要多加NodeJS这一层? 多加一层,性能怎么样? 多加一层,前端的工作量是不是增加了? 多加一层就多一层风险,怎么破? NodeJS什么都能做,为什么还要JAVA?这些问题要说清楚不容易,下面说下我的认识过程。3.2 为什么要增加一层NodeJS?现阶段我们主要以后端MVC的模式进行开发,这种模式严重阻碍了前端开发效率,也让后端不能专注于业务开发。解决方案是让前端能控制Controller层,但是如果在现有技术体系下很难做到,因为不可能让所有前端都学java,安装后端的开发环境,写VM。NodeJS就能很好的解决这个问题,我们无需学习一门新的语言,就能做到以前开发帮我们做的事情,一切都显得那么自然。3.3 性能问题分层就涉及每层之间的通讯,肯定会有一定的性能损耗。但是合理的分层能让职责清晰、也方便协作,会大大提高开发效率。分层带来的损失,一定能在其他方面的收益弥补回来。另外,一旦决定分层,我们可以通过优化通讯方式、通讯协议,尽可能把损耗降到最低。举个例子:淘宝宝贝详情页静态化之后,还是有不少需要实时获取的信息,比如物流、促销等等,因为这些信息在不同业务系统中,所以需要前端发送5,6个异步请求来回填这些内容。有了NodeJS之后,前端可以在NodeJS中去代理这5个异步请求,还能很容易的做Bigpipe,这块的优化能让整个渲染效率提升很多。可能在PC上你觉得发5,6个异步请求也没什么,但是在无线端,在客户手机上建立一个HTTP请求开销很大,有了这个优化,性能一下提升好几倍。淘宝详情基于NodeJS的优化我们正在进行中,上线之后我会分享一下优化的过程。3.4 前端的工作量是否增加了?相对于只切页面/做demo,肯定是增加了一点,但是当前模式下有联调、沟通环节,这个过程非常花时间,也容易出bug,还很难维护。所以,虽然工作量会增加一点,但是总体开发效率会提升很多。另外,测试成本可以节省很多。以前开发的接口都是针对表现层的,很难写测试用例。如果做了前后端分离,甚至测试都可以分开,一拨人专门测试接口,一拨人专注测试UI(这部分工作甚至可以用工具代替)。3.5 增加Node层带来的风险怎么控制?随着Node大规模使用,系统/运维/安全部门的同学也一定会加入到基础建设中,他们会帮助我们去完善各个环节可能出现的问题,保障系的稳定性。3.6 Node什么都能做,为什么还要JAVA?我们的初衷是做前后端分离,如果考虑这个问题就有点违背我们的初衷了。即使用Node替代Java,我们也没办法保证不出现今天遇到的种种问题,比如职责不清。我们的目的是分层开发,专业的人,专注做专业的事。基于JAVA的基础架构已经非常强大而且稳定,而且更适合做现在架构的事情。四、淘宝基于Node的前后端分离上图是我理解的淘宝基于Node的前后端分离分层,以及Node的职责范围。简单解释下: 最上端是服务端,就是我们常说的后端。后端对于我们来说,就是一个接口的集合,服务端提供各种各样的接口供我们使用。因为有Node层,也不用局限是什么形式的服务。对于后端开发来说,他们只用关心业务代码的接口实现。 服务端下面是Node应用。 Node应用中有一层Model Proxy与服务端进行通讯。这一层主要目前是抹平我们对不同接口的调用方式,封装一些view层需要的Model。 Node层还能轻松实现原来vmcommon,tms(引用淘宝内容管理系统)等需求。 Node层要使用什么框架由开发者自己决定。不过推荐使用express+xTemplate的组合,xTemplate能做到前后端公用。 怎么用Node大家自己决定,但是令人兴奋的是,我们终于可以使用Node轻松实现我们想要的输出方式:JSON/JSONP/RESTful/HTML/BigPipe/Comet/Socket/同步、异步,想怎么整就怎么整,完全根据你的场景决定。 浏览器层在我们这个架构中没有变化,也不希望因为引入Node改变你以前在浏览器中开发的认知。 引入Node,只是把本该就前端控制的部分交由前端掌控。这种模式我们已经有两个项目在开发中,虽然还没上线,但是无论是在开发效率,还是在性能优化方面,我们都已经尝到了甜头。五、我们还需要要做什么? 把Node的开发流程集成到淘宝现有的SCM流程中。 基础设施建设,比如session,logger等通用模块。 最佳开发实践 线上成功案例 大家对Node前后端分离概念的认识 安全 性能 技术上不会有太多需要去创新和研究的,已经有非常多现成的积累。其实关键是一些流程的打通和通用解决方案的积累,相信随着更多的项目实践,这块慢慢会变成一个稳定的流程。六、“中途岛”虽然“基于NodeJS的全栈式开发”模式很让人兴奋,但是把基于Node的全栈开发变成一个稳定,让大家都能接受的东西还有很多路要走,我们正在进行的“中途岛”项目就是为了解决这个问题。虽然我们起步不久,但是离目标已经越来越近!标签:midway、NodeJS、前后端分离前后端分离的思考与实践(二)作者:Herman|时间:2014-04-10 20:19基于前后端分离的模版探索前言在做前后端分离时,第一个关注到的问题就是渲染,也就是View这个层面的工作。在传统的开发模式中,浏览器端与服务器端是由不同的前后端两个团队开发,但是模版却又在这两者中间的模糊地带。因此模版上面总不可避免的越来越多复杂逻辑,最终难以维护。而我们选择了NodeJS,作为一个前后端的中间层。试图藉由NodeJS,来疏理View层面的工作。使得前后端分工更明确,让专案更好维护,达成更好的用户体验。本文渲染这块工作,对于前端开发者的日常工作来说,佔了非常大的比例,也是最容易与后端开发纠结不清的地方。回首过去前端技术发展的这几年,View这个层面的工作,经过了许多次的变革,像是:1. Form Submit 全页刷新 =AJAX局部刷新2. 服务端续染 + MVC =客户端渲染 + MVC3. 传统换页跳转 = 单页面应用可以观察到在这几年,大家都倾向将渲染这件事,从服务器端端移向了浏览器端。而服务器端则专注于服务化,提供数据接口。浏览器端渲染的好处浏览器端渲染的好处,我们都很清楚,像是1. 摆脱业务逻辑与呈现逻辑在Java模版引擎中的耦合与混乱。2. 针对多终端应用,更容易以接口化的形式。在浏览器端搭配不同的模版,呈现不同的应用。3. 页面呈现本来就不仅是html,在前端的渲染可以更轻易的以组件化形式 (html + js + css)提供功能,使得前端组件不需依赖于服务端产生的html结构。4. 脱离对于后端开发、发佈流程的依赖。5. 方便联调。浏览器端渲染造成的坏处但是在享受好处的同时,我们同样的也面临了浏览器端渲染所带来的坏处,像是:1. 模版分离在不同的库。有的模版放在服务端 (JAVA),而有的放在浏览器端 (JS)。前后端模版语言不相通。2. 需要等待所有模版与组件在浏览器端载入完成后才能开始渲染,无法即开即看。3. 首次进入会有白屏等待渲染的时间,不利于用户体验4. 开发单页面应用时,前端Route与服务器端Route不匹配,处理起来很麻烦。5. 重要内容都在前端组装,不利于SEO反思前后端的定义其实回头想想,在我们把渲染的工作从 服务端(Java) 抽出来到 浏览器端(JS) 的时候,我们的目的只是明确的前后端职责划分,并不是非浏览器渲染不可。只是因为在传统的开发模式中,出了服务器就到了浏览器,所以前端的工作内容只能被限制在浏览器端。也因此很多人认定了后端 = 服务端前端 = 浏览器端,就像下面这张图。而在淘宝UED目前进行的中途岛Midway项目中,藉由在 JAVA Browser中间搭建一个NodeJS中间层,试图把这个前后端的分割线,重新针对工作职责去区分,而非针对硬体环境去区分(服务器 & 浏览器)。因此我们有机会做到模版与路由的共享,也是一个前后端分工中最理想的状态。淘宝中途岛 Midway在中途岛项目中,我们把前后端分界的那条线,从浏览器端移回到了服务器端。藉由一个由前端轻松掌控且与浏览器共通的Nodejs层,可以更清晰的完成了前后端分离。也可以让前端开发针对不同的情况,自行决定最适当的解决方案。而不是所有事情都在浏览器端来处理。职责划分中途岛并不是前端试图抢后端饭碗的项目,目的只是把模版这个模糊地带切割清楚,取得更明确的职责划分。 后端 (JAVA),专注于1. 服务层2. 数据格式、数据稳定3. 业务逻辑 前端,专注于1. UI层2. 控制逻辑、渲染逻辑3. 交互、用户体验而不再拘泥于服务端或浏览器端的差异。模版共享在传统的开发模式中,浏览器端与服务器端是由不同的前后端两个团队开发,但是模版却又在这两者中间的模糊地带。因此模版上面总不可避免的越来越多复杂逻辑,最终难以维护。有了NodeJS,后端同学可以在JAVA层专注于业务逻辑与数据的开发。而前端同学则专注于控制逻辑与渲染的开发。并且自行选择这些模版是要在服务端 (NodeJS)或是浏览器端做渲染。用著一样的模版语言XTemplate,一样的渲染引擎JavaScript在不同的渲染环境(Server-side、PC Browser、Mobile Browser、Web View、etc.) 渲染出一样的结果。路由共享也因为有了NodeJS这一层,可以更细致的控制路由。假如需要在前端做浏览器端路由时,可以同时配置服务器端的路由,使其在浏览器端换页或是服务端换页,都可以得到一致的渲染效果。同时也处理了SEO的问题。模版共享的实践通常我们在浏览器端渲染一份模版时,流程不外乎是1. 在浏览器端載入模版引擎 (xtmpleate, juicer, handlerbar, etc.)2. 在浏览器端载入模版档案,方法可能有 使用 . 印在页面上 使用模块载入工具,载入模版档案 (KISSY, requireJS, etc.) 其他3. 取得数据,使用模版引擎产生html4. 将html插入到指定位置。從以上的流程可以觀察到,要想要做到模版的跨端共享,重点其实在一致的模块选型这件事。市面上流行很多种模块标准,例如 KMD、AMD、CommonJS,只要能将NodeJS的模版档案透过一致模块规范输出到NodeJS端,就可以做基本的模版共享了。而后续的系列文章会针对Model的proxy与共享,做进一步的探讨。案例探讨因为有了中途岛这中间层,针对过往的一些问题都有了更好的解答,例如说案例一 复杂交互应用 (如购物车、下单页面) 状况:全部的HTML都是在前端渲染完成,服务端仅提供接口。 问题:进入页面时,会有短暂白屏。 解答:1. 首次进入页面,在NodeJS端进行全页渲染,并在背景下载相关的模版。2. 后续交互操作,在浏览器端完成局部刷新3. 用的是同一份模版, 产生一样的结果案例二 单页面应用 状况:使用Client Side MVC框架,在浏览器换页。 问题:渲染与换页都在浏览器端完成,直接输入网址进入或f5刷新时,无法直接呈现同样的内容。 解答:1. 在浏览器端与NodeJS端共享同样的Route设定2. 浏览器端换页时,在浏览器端进行Route变更与页面内容渲染3. 直接输入同样的网址时,在NodeJS端进行页面框架 + 页面内容渲染4. 不管是浏览器端换页,或直接输入同样的网址,看到的内容都是一样的。5. 除了增加体验、减少逻辑複杂度外。更解决了SEO的问题案例三 纯浏览型页面 状况:页面仅提供资讯,较少或没有交互 问题:html在服务端产生,css与js放在另外一个位置,彼此间有依赖。 解答:1. 透过NodeJS,统一管理html + css + js2. 日后若需要扩展成复杂应用或是单页面应用,也可以轻易转移。案例四 跨终端页面 状况:同样的应用要在不同端点呈现不同的介面与交互 问题:html管理不易,常常会在服务端产生不一样的html,浏览器端又要做不一样的处理 解答:1. 跨终端的页面是渲染的问题,统一由前端来处理。2. 透过NodeJS层与后端服务化,可以针对这类型复杂应用,设计最佳的解决方案。总结过去的AJAX、Client-side MVC、SPA、Two-way Data Binding 等技术的出现,都是试图要解决当时的前端开发遇到的瓶颈。而NodeJS中间层的出现,也是在试图解决现今前端被侷限在浏览器端的一个限制。这边文章专注于前后端模版共享,也希望能抛砖引玉,与大家一起讨论如何在NodeJS中间层这个架构下,我们可以怎样的改善我们的工作流程,怎样的跟后端配合,来把前端这个工作做得更好。前后端分离的思考与实践(三)作者:善繁|时间:2014-04-13 20:01Midway-ModelProxy 轻量级的接口配置建模框架前言使用Node做前后端分离的开发模式带来了一些性能及开发流程上的优势(见前后端分离的思考与实践 一), 但同时也面临不少挑战。在淘宝复杂的业务及技术架构下,后端必须依赖Java搭建基础架构,同时提供相关业务接口供前端使用。Node在整个环境中最重要的工作之一就是代理这些业务接口,以方便前端(Node端和浏览器端)整合数据做页面渲染。如何做好代理工作,使得前后端开发分离之后,仍然可以在流程上无缝衔接,是我们需要考虑的问题。本文将就该问题做相关探讨,并提出解决方案。由于后端提供的接口方式可能多种多样,同时开发人员在编写Node端代码访问这些接口的方式也有可能多种多样。如果我们在接口访问方式及使用上不做统一架构处理,则会带来以下一些问题:1. 每一个开发人员使用各自的代码风格编写接口访问代码,造成工程目录及编码风格混乱,维护相对困难。2. 每一个开发人员编写自己的mock数据方式,开发完毕之后,需要手工修改代码移除mock。3. 每一个开发人员为了实现接口的不同环境切换(日常,预发,线上),可能各自维护了一些配置文件。4. 数据接口调用方式无法被各个业务model非常方便地复用。5. 对于数据接口的描述约定散落在代码的各个角落,有可能跟后端人员约定的接口文档不一致。6. 整个项目分离开发之后,对于接口的联调或者测试回归成本依然很高,需要涉及到每一个接口提供者和使用者。于是我们希望有这样一个框架,通过该框架提供的机制去描述工程项目中依赖的所有外部接口,对他们进行统一管理,同时提供灵活的接口建模及调用方式,并且提供便捷的线上环境和生产环境切换方法,使前后端开发无缝结合。ModelProxy就是满足这样要求的轻量级框架,它是Midway Framework 核心构件之一,也可以单独使用。使用ModelProxy可以带来如下优点:1. 不同的开发者对于接口访问代码编写方式统一,含义清晰,降低维护难度。2. 框架内部采用工厂+单例模式,实现接口一次配置多次复用。并且开发者可以随意定制组装自己的业务Model(依赖注入)。3. 可以非常方便地实现线上,日常,预发环境的切换。4. 内置river-mock和mockjs等mock引擎,提供mock数据非常方便。5. 使用接口配置文件,对接口的依赖描述做统一的管理,避免散落在各个代码之中。6. 支持浏览器端共享Model,浏览器端可以使用它做前端数据渲染。整个代理过程对浏览器透明。7. 接口配置文件本身是结构化的描述文档,可以使用river工具集合,自动生成文档。也可使用它做相关自动化接口测试,使整个开发过程形成一个闭环。ModelProxy工作原理图及相关开发过程图览在上图中,开发者首先需要将工程项目中所有依赖的后端接口描述,按照指定的json格式,写入interface.json配置文件。必要时,需要对每个接口编写一个规则文件,也即图中interface rules部分。该规则文件用于在开发阶段mock数据或者在联调阶段使用River工具集去验证接口。规则文件的内容取决于采用哪一种mock引擎(比如 mockjs, river-mock 等等)。配置完成之后,即可在代码中按照自己的需求创建自己的业务model。下面是一个简单的例子:【例一】 第一步 在工程目录中创建接口配置文件interface.json, 并在其中添加主搜接口json定义 title: pad淘宝项目数据接口集合定义, version: 1.0.0, engine: mockjs, rulebase: ./interfaceRules/, status: online, interfaces: name: 主搜索接口, id: Search.getItems, urls: online: /client/search.do 第二步 在代码中创建并使用model/ 引入模块var ModelProxy = require( modelproxy ); / 全局初始化引入接口配置文件 (注意:初始化工作有且只有一次)ModelProxy.init( ./interface.json );/ 创建model 更多创建模式请参后文var searchModel = new ModelProxy( searchItems: Search.getItems / 自定义方法名: 配置文件中的定义的接口ID );/ 使用model, 注意: 调用方法所需要的参数即为实际接口所需要的参数。searchModel.searchItems( q: iphone6 ) / !注意 必须调用 done 方法指定回调函数,来取得上面异步调用searchItems获得的数据! .done( function( data ) console.log( data ); ) .error( function( err ) console.log( err ); );ModelProxy的功能丰富性在于它支持各种形式的profile以创建需要业务model: 使用接口ID创建生成的对象会取ID最后.号后面的单词作为方法名ModelProxy.create( Search.getItem ); 使用键值JSON对象自定义方法名: 接口IDModelProxy.create( getName: Session.getUserName, getMyCarts: Cart.getCarts ); 使用数组形式取最后 . 号后面的单词作为方法名下例中生成的方法调用名依次为: Cart_getItem, getItem, suggest, getNameModelProxy.create( Cart.getItem, Search.getItem, Search.suggest, Session.User.getName ); 前缀形式所有满足前缀的接口ID会被引入对象,并取其后半部分作为方法名ModelProxy.create( Search.* );同时,使用这些Model,你可以很轻易地实现合并请求或者依赖请求,并做相关模板渲染【例二】 合并请求var model = new ModelProxy( Search.* );/ 合并请求 (下面调用的model方法除done之外,皆为配置接口id时指定)model.suggest( q: 女 ) .list( keyword: iphone6 ) .getNav( key: 流行服装 ) .done( function( data1, data2, data3 ) / 参数顺序与方法调用顺序一致 console.log( data1, data2, data3 ); );【例三】 依赖请求var model = new ModelProxy( getUser: Session.getUser, getMyOrderList: Order.getOrder );/ 先获得用户id,然后再根据id号获得订单列表model.getUser( sid: fdkaldjfgsakls0322yf8 ) .done( function( data ) var uid = data.uid; / 二次数据请求依赖第一次取得的id号 this.getMyOrderList( id: uid ) .done( function( data ) console.log( data ); ); );此外ModelProxy不仅在Node端可以使用,也可以在浏览器端使用。只需要在页面中引入官方包提供的modelproxy-client.js即可。【例四】浏览器端使用ModelProxy KISSY.use( modelproxy, function( S, ModelProxy ) / !配置基础路径,该路径与第二步中配置的拦截路径一致! / 且全局配置有且只有一次! ModelProxy.configBase( /model/ ); / 创建model var searchModel = ModelProxy.create( Search.* ); searchModel .list( q: ihpone6 ) .list( q: 冲锋衣 ) .suggest( q: i ) .getNav( q: 滑板 ) .done( function( data1, data2, data3, data4 ) console.log( list_ihpone6: data1, list_冲锋衣: data2, suggest_i: data3, getNav_滑板: data4 ); ); );同时,ModelProxy可以配合Midway另一核心组件Midway-XTPL一起使用,实现数据和模板以及相关渲染过程在浏览器端和服务器端的全共享。关于ModelProxy的详细教程及文档请移步/purejs/modelproxy总结ModelProxy以一种配置化的轻量级框架存在,提供友好的接口model组装及使用方式,同时很好的解决前后端开发模式分离中的接口使用规范问题。在整个项目开发过程中,接口始终只需要定义描述一次,前端开发人员即可引用,同时使用River工具自动生成文档,形成与后端开发人员的契约,并做相关自动化测试,极大地优化了整个软件工程开发过程。【注】River 是阿里集团研发的前后端统一接口规范及相关工具集合的统称前后端分离的思考与实践(四)作者:lorrylockie|时间:2014-05-09 17:42前后端分离模式下的安全解决方案前言在前后端分离的开发模式中,从开发的角色和职能上来讲,一个最明显的变化就是:以往传统中,只负责浏览器环境中开发的前端同学,需要涉猎到服务端层面,编写服务端代码。而摆在面前的一个基础性问题就是如何保障Web安全?本文就在前后端分离模式的架构下,针对前端在Web开发中,所遇到的安全问题以及应对措施和注意事项,并提出解决方案。跨站脚本攻击(XSS)的防御问题及解决思路跨站脚本攻击(XSS,Cross-site scripting)是最常见和基本的攻击Web网站的方法。攻击者可以在网页上发布包含攻击性代码的数据,当浏览者看到此网页时,特定的脚本就会以浏览者用户的身份和权限来执行。通过XSS可以比较容易地修改用户数据、窃取用户信息以及造成其它类型的攻击,例如:CSRF攻击。预防XSS攻击的基本方法是:确保任何被输出到HTML页面中的数据以HTML的方式进行转义(HTML escape)。例如下面的模板代码:1. $description这段代码中的$description为模板的变量(不同模板中定义的变量语法不同,这里只是示意一下),由用户提交的数据,那么攻击者可以输入一段包含”JavaScript”的代码,使得上述模板语句的结果变成如下的结果:1. 2. alert(hello)3. 上述代码,在浏览器中渲染,将会执行JavaScript代码并在屏幕上alert hello。当然这个代码是无害的,但攻击者完全可以创建一个JavaScript来修改用户资料或者窃取cookie数据。解决方法很简单,就是将$description的值进行html escape,转义后的输出代码如下1. 2. </textarea><script>alert("hello!")</script>3. 以上经过转义后的HTML代码是没有任何危害的。Midway的解决方案转义页面中所有用户输出的数据对数据进行转义有以下几种情况和方法:1. 使用模板内部提供的机制进行转义中途岛内部使用KISSY xtemplate作为模板语言。在xtemplate实现中,语法上使用两个中括号(val)解析模板数据, ,默认既是对数据进行HTML转义的,所以开发者可以这样写模板:1. description在xtemplate中,如果不希望输出的数据被转义,需要使用三个中括号(val)。2. 在Midway中明确的调用转义函数开发者可以在Node.js程序或者模板中,直接调用Midway提供的HTML转义方法,显示的对数据进行转义,如下:方法1:在Node.js程序中对数据进行HTML转义1. varSecurity=require(midway-security);2. /data from server,eg html:,other:3. data.html=Security.escapeHtml(data.html);4. xtpl=xtpl.render(data);方法2:在模板中对HTML数据进行HTML转义1. Security.escapeHtml(description)注意:只有当模板内部没有对数据进行转义的时候才使用Security.escapeHtml进行转义。 否则,模板内部和程序会两次转义叠加,导致不符合预期的输出。推荐:如果使用xtemplate,建议直接使用模板内置的进行转义; 如果使用其他模板,建议使用Security.escapeHtml进行转义。过滤页面中用户输出的富文本你可能会想到:“其实我就是想输出富文本,比如一些留言板、论坛给用户提供一些简单的字体大小、颜色、背景等功能,那么我该如何处理这样的富文本来防止XSS呢?”1. 使用Midway中Security提供的richText函数Midway中提供了richText方法,专门用来过滤富文本,防止XSS、钓鱼、cookie窃取等漏洞。有一个留言板,模板代码可能如下:1. 2. message3. 因为message是用户的输入数据,其留言板的内容,包含了富文本信息,所以这里在xtemplate中,使用了三个大括号,默认不进行HTML转义;那么用户输入的数据假如如下:1. 我在留言中上述的富文本数据如果直接输出到页面中,必然会导致站点的js注入到当前页面中,造成了XSS攻击。为了防止这个漏洞,我们只要在模板或者程序中,调用Security.richText方法,处理用户输入的富文本。调用方法与escapeHtml类似,有如下两种方式方法1: 直接在Node.js程序中调用1. message=Security.richText(message);2. varhtml=xtpl.render(message)方法2: 在模板中调用1. 2. Security.richText(message)3. 通过调用Security的richText方法后,最终的输出如下:1. 2. 我在留言中3. 可以看出,首先:会造成XSS攻击的script标签被直接过滤掉;同时style标签中CSS属性position:fixed;样式也被过滤了。最终输出了无害的HTML富文本了解其他可能导致XSS攻击的途径除了在页面的模板中可能存在XSS攻击之外,在Web应用中还有其他几个途径也可能会有风险。1. 出错页面的漏洞一个页面如果找不到,系统可能会报一个404 Not Found的错误,例如:http:/localhost/page/not/found1. 404NotFound2. Page/page/not/found doesnotexsit很显然:攻击者可以利用这个页面,构造一个类似这样的连接,http:/localhost/%3Cscript%3Ealert%28%27hello%27%29%3C%2Fscript%3E,并引诱受害者点击 ;假如出错页面未对输出变量进行转义的话,那么连接中隐藏的alert(hello)将会被执行。在express中,发送一个404页面的方法如下1. res.send(404,Sorry,we dont find that!)这里就需要开发者注意错误页面(404或者其他错误状态)的处理方式。如果错误信息的返回内容带有路径信息(其实更准确的讲,是用户输入信息),就一定要进行escapeHtml了。后续,错误处理的安全机制,会在Midway框架层面中完成。Midway解决方案的补充说明其他模板引擎Midway默认支持xtemplate模板,但将来也有可能支持其他模板:如jade、mustache、ejs等。目前在主流模板中,都提供了默认转义和不转义的输出变量写法,需要开发者特别留意其安全性。关于escape的其他支持除了对页面中输出的普通数据和富文本数据,一些场景中也还包含其他可能需要转义的情况,Midway提供了如下几个常用的转义方法,供开发者使用: escapeHtml 过滤指定的HTML中的字符,防XSS漏洞 jsEncode 对输入的String进行JavaScript 转义 对中文进行unicode转义,单引号,双引号转义 escapeJson 不破坏JSON结构的escape函数,只对json结构中name和vaule做escapeHtml处理 escapeJsonForJsVar 可以理解就是jsEncode+escapeJson例子如下1. varjsonText=:;2. console.log(SecurityUtil.escapeJson(jsonText);/ <script>:<script>3.4. varjsonText=你好:;5. console.log(SecurityUtil.escapeJsonForJsVar(jsonText);/u4f60u597d:<script>6.7. varstr=alert(你好);8. console.log(SecurityUtil.jsEncode(str);/ alert(u4f60u597d)跨站请求伪造攻击(CSRF)的预防问题及解决思路名词解释:表单:泛指浏览器端用于客户端提交数据的形式;包括a标签、ajax提交数据、form表单提交数据等,而非对等于HTML中的form标签。跨站请求伪造(CSRF,Cross-site request forgery)是另一种常见的攻击。攻击者通过各种方法伪造一个请求,模仿用户提交表单的行为,从而达到修改用户的数据或执行特定任务的目的。为了假冒用户的身份,CSRF攻击常常和XSS攻击配合起来做,但也可以通过其它手段:例如诱使用户点击一个包含攻击的链接。解决CSRF攻击的思路分如下两个步骤1. 增加攻击的难度。GET请求是很容易创建的,用户点击一个链接就可以发起GET类型的请求,而POST请求相对比较难,攻击者往往需要借助JavaScript才能实现;因此,确保form表单或者服务端接口只接受POST类型的提交请求,可以增加系统的安全性。2. 对请求进行认证,确保该请求确实是用户本人填写表单或者发起请求并提交的,而不是第三者伪造的。一个正常用户修改网站信息的过程如下 用户请求修改信息(1) - 网站显示用户修改信息的表单(2) - 用户修改信息并提交(3) - 网站接受用户修改的数据并保存(4)而一个CSRF攻击则不会走这条路线,而是直接伪造第2步用户提交信息 直接跳到第2步(1) - 伪造要修改的信息并提交(2) - 网站接受攻击者修改参数数据并保存(3)只要能够区分这两种情况,就能够预防CSRF攻击。那么如何区分呢? 就是对第2步所提交的信息进行验证,确保数据源自第一步的表单。具体的验证过程如下: 用户请求修改信息(1) - 网站显示用于修改信息的空白表单,表单中包含特殊的token同时把token保存在session中(2) - 用户修改信息并提交,同时发回token信息到服务端(3) - 网站比对用户发回的token和session中的token,应该一致,则接受用户修改的数据,并保存这样,如果攻击者伪造要修改的信息并提交,是没办法直接访问到session的,所以也没办法拿到实际的token值;请求发送
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 宋韵在苏轼美学中的呈现动态
- 健康传播相关试题及答案
- 行政法学优化政策执行的路径研究试题及答案
- 行政法学前景展望试题及答案
- 执业护士考试的知识体系构建及试题答案
- 2025年执业医师考试实践试题及答案
- 2025年自考行政管理就业前景试题及答案归纳
- 护士执行力2025年执业考试试题与答案
- 准备2025年文化概论考试的试题及答案清单
- 2025年自考行政管理目标管理题及答案
- 幼儿园绘本故事:《十二生肖》 课件
- 2022年湘潭职业技术学院中职部教师招聘笔试题库及答案解析
- 小学数学北师大五年级下册七用方程解决问题相遇问题导学单
- 新媒体运营知识考核试题与答案
- 金属材料的主要性能ppt课件(完整版)
- “新时代好少年”推荐表
- 规章制度文件评审表
- 草坪学实习报告模板-Copy
- K-H-V行星齿轮减速器 瞿鸿鹏
- 初中道德与法治课课堂课堂评价表
- sales-contract(中英文详版)
评论
0/150
提交评论