翁湦元,單杏花,朱建軍,王雪峰
(中國鐵道科學研究院集團有限公司 電子計算技術研究所,北京 100081)
隨著前端技術的飛速發展,如今的Web開發已不僅局限于HTML+CSS+javascript的傳統開發模式。HTML5,ES6,ES2017等新技術標準陸續實施,Nodejs,TypeScript等新技術的推廣與普及,前端開發正逐漸朝著標準化、規模化、模塊化方向發展[1]。
Angular2是Google開發的前端框架與微軟所推廣的TypeScript相結合的產物,具有深厚的技術背景,是一個適合編寫大型應用的框架[2]。通過編譯為ES6標準的Javascript代碼在客戶端運行。Angular2引入了模塊化、依賴注入、MVVM(Model-View-ViewModel)設計模式[3]等后端開發等理念,以完整工程的思想管理前端項目。同時Angular2將Web項目的包裝為單一頁面應用(SPA,Single Page Application,)的形式,減少了頁面請求次數,使頁面響應、切換更迅速,顯著提升用戶瀏覽體驗。
本文以Angular2開發框架為基礎,在開發實踐的基礎上進行總結,以保障應用安全、提高開發效率、提升用戶體驗為目的,分別從應用分層、應用安全和應用性能優化角度提出應用開發架構的關鍵設計和實現方法。
MVVM模式是傳統MVC(Model-View-Controller)設計模式的進一步發展的產物。MVVM模式將原本數據、邏輯與頁面一體的混合開發模式拆分為模型、視圖兩個層次進行開發,并由一個ViewModel將視圖與模型進行雙向綁定,View僅關心用戶交互部分、響應ViewModel的事件;ViewModel負責封裝業務邏輯,并把數據模型的變化傳遞給視圖,從而達到松散耦合的效果,提高了開發效率[4]。MVVM設計模式如圖1所示。
傳統的Web應用將頁面渲染工作由服務端完成,因此服務端在承擔常規業務計算壓力的同時也要承擔頁面渲染的計算壓力,造成客戶端頁面響應緩慢,流量消耗大的問題[5]。

圖1 MVVM設計模式示意圖
SPA應用僅在用戶第一次訪問Web時獲取完整的HTML以及靜態資源文件,此后的用戶交互均通過Ajax(Asynchronous Javascript And XML)請求的方式與服務器進行通信,服務器僅負責處理常規的業務計算,并以JSON(JavaScript Object Notation)格式響應。這樣客戶端僅需要根據數據更新局部頁面,提高了響應性能、減少了大量不必要的數據傳輸。
Angular2參考了Java的Spring框架中的依賴注入概念,將對象之間的依賴關系由容器管理,以移除類之間的依賴。提高了代碼的靈活性與可維護性。
在Angular2框架的基礎上,對Web應用架構進一步設計,以達到提高開發效率、保障應用安全的目的。以下分別從應用架構設計以及應用安全設計兩個方面進行闡述。
2.1.1 基礎結構
Angular2應用中基礎模塊和服務通過依賴注入方式進行管理,組成了應用的基本模型與邏輯層,由類似HTML風格編寫的指令(Directive)形成模板(Template)結合組件(Component)通過雙向綁定組成了模型視圖層從而展現應用的內容,并根據指令響應用戶的交互。Angular2的基礎應用結構如圖2所示。

圖2 Angular2基礎結構說明
2.1.2 應用分層
(1)基礎層
應用基礎層包含Angular2啟動的必要代碼,即:應用主程序、根模塊、根路由以及根組件;同時應用底層的配置常量信息放置在應用基礎層中。
(2)公共服務層
公共服務層將各業務模塊及組件可以共同使用的公共函數代碼封裝為公共服務和工具類,并在應用啟動時完成初始化,以供業務模塊和組件進行調用。這些公共服務層代碼與應用業務不直接相關。
(3)業務模塊層
Angular2中視圖與邏輯以及頁面數據被封裝為了組件(Component)。組件負責控制屏幕上的一小塊視圖區域。視圖層的組件是Angular2應用與用戶交互的基本功能單元。實際場景中一個應用往往包含眾多組件,因此為有效管理各組件,使應用功能結構更為清晰,以“高內聚、低耦合”為原則,將功能相關的若干組件進行封裝,變為獨立的模塊。每個功能模塊均有各自的模塊定義、路由管理、服務和組件。
通過業務模塊劃分,將分散的組件、服務歸納集中于各功能模塊之內,從而將模塊打造成自給自足的生態系統。合理設計的模塊可以很方便地移植到其它應用當中而不需要代碼修改,有利于代碼的復用。同時,Angular2的模塊化設計使得應用支持模塊的動態加載機制,各模塊按需加載,起到了加快應用啟動速度、節省網絡帶寬以及保護代碼安全的作用。
模塊化應用架構分層設計如圖3所示。
2.1.3 模塊加載策略
基礎層是應用啟動的入口,為簡化模塊加載過程,保留一個業務模塊,并將其組件、服務等部分分別命名為:Module,ModuleRoute,ModuleService,ModuleComponent。從應用啟動到最終業務模塊的加載流程如圖4所示。
根模塊(RootModule)啟動后將載入根路由(RootRoutes)、公共服務層的公共服務(CommonServices),并載入和展示根組件(RootComponent)。同時,其余業務模塊(Module)在Angular2默認的配置下會預先載入,業務模塊內的路由(ModuleRoutes)、業務服務(ModuleService)以及模塊內組件(ModuleComponent)均會在后臺相繼完成初始化動作。當用戶在根組件中點擊觸發頁面跳轉時才會進入業務模塊,并由業務模塊的路由引導激活并展示相應的組件。

圖3 模塊化應用架構分層設計

圖4 模塊加載策略
2.2.1 模塊安全與組件安全
有別于傳統Web應用,用戶的訪問權限控制可以在后端完成。由于前端項目的代碼必須在客戶端瀏覽器環境下執行,用戶可以輕易獲取前端項目的邏輯代碼,因此安全措施是必須的。從圖4可以看出,Angualr2默認將在應用啟動時加載全部模塊,需要采取一定的保護措施。以下將分別從模塊載入和組件激活兩方面進行闡述。
(1)模塊安全
選取手術室急診患者110例作為研究對象,根據護理方法將其分成兩組。其中,對照組男28例,女25例,年齡34~72歲,平均年齡(53.85±4.72)歲;觀察組男29例,女28例,年齡31~74歲,平均年齡(54.28±4.51)歲。兩組患者的一般資料對比,差異無統計學意義(P>0.05)。
將應用按照業務進行模塊化劃分后,通過Angular2官方提供的CanLoad接口來控制模塊的載入與否。對于用戶無權訪問的模塊,將不被載入客戶端,從而保護了模塊代碼的安全。

以上代碼即為CanLoad接口的一種實現,若用戶為已登錄狀態,則可以載入受保護的模塊,否則無法載入。同時在載入模塊的路由配置中加載該CanLoad接口的實現類。

以上代碼通過對路由的CanLoad的參數注入,在業務模塊加載前實現模塊的安全保護。
(2)組件安全
對于已載入模塊,用戶若無權訪問模塊內部的組件,應用也不應予以展示。與模塊安全保護類似,通過實現CanActivate接口控制組件的展示與否。

以上代碼即為CanActivate接口的一種實現,若用戶為已登錄狀態,則可以激活并展示相應組件,否則跳轉至登錄頁面,待用戶完成登錄認證后再跳轉回原頁面。

上述代碼通過對路由的CanActivate的參數注入,實現組件的保護。
綜上所述,CanLoad通過權限設置使未授權代碼不被載入用戶終端,從而保護了代碼安全;CanActivate通過權限設置使未授權代碼不被激活執行,從而保證了應用安全。兩者共同構成了Angular2應用層面的安全屏障。
通過Ajax請求與服務端交互是Angualr2應用的基本交互模式,服務端會對外暴露很多數據接口。因此,對數據接口的保護是必須的。服務端防護主要通過CSRF和Spring Security來完成[6]。
(1)CSRF防護
CSRF(Cross-site request forgery)是一種廣泛存在的網站漏洞,通過隱式攜帶用戶的登錄信息從第三方網站發起惡意操作[7]。在同一會話中,通過在提交的數據中提供一個不可預測的隨機數標識來確保提交數據的合法性,從而過濾了第三方網站的惡意數據,保證了只有真正訪問Web應用的用戶才有權限訪問數據接口。該隨機數標識被稱為csrf-token。
(2)權限驗證
CSRF防護僅能保證數據的合法性,但不能保證接口的操作權限得到有效控制,因此必須在后端服務上增加一套安全驗證機制[8]。
現有Web應用的安全驗證框架有很多,我們采用較為成熟的Spring Security進行說明[9]。Spring Security是Spring Framework基礎上最成熟的安全系統[10],通過 IOC(Inversion of Control)和 AOP(Aspect Oriented Programming)機制實現了原項目的無侵入式快速部署,應用邏輯與安全邏輯的分離。
Spring Security的權限驗證流程如圖5所示。

圖5 權限驗證流程
2.2.3 應用安全設計小結
通過對模塊安全、組件安全和后端接口安全的設計,最終達到了未授權模塊禁止加載,未授權組件禁止顯示,未授權接口禁止調用的效果。最大程度地保障了應用的代碼與數據的安全。
(1)加速資源載入:通過nginx反向資源代理可以有效減輕Web服務端網絡負載壓力;通過CDN資源加速可有效加快用戶從網絡下載應用js/css靜態資源的速度。
(2)縮短啟動時間:通過啟用Angular2應用生產環境編譯選項可以有效縮小應用最終js文件的大??;開啟AOT(Ahead-of-time)編譯,可以有效提高應用在客戶端的執行速度,縮短初始化時間。
由于SPA應用已經最大限度縮短了頁面切換的時間,因此進一步優化應用響應速度的空間在于加速數據接口的響應速度。通過有效利用HTML5的storage本地存儲特性,可以將頻繁查詢的數據寫入緩存。頁面加載直接使用緩存數據,并在后臺調用接口查詢,僅在數據與緩存出現差異時再重繪界面。緩存優化流程如圖6所示。

圖6 緩存優化流程
由圖6可以看出,在理想狀況下若緩存命中,則頁面數據直接從緩存獲取,完全沒有數據查詢與加載的耗時,而即使數據與緩存出現差異,也只重繪數據變化的部分,最終頁面的展示耗時與未加緩存的耗時相同。
本文以Angular2框架為基礎,闡述了Angular2框架的優勢,提出了模塊化Web應用的架構設計,設計內容包括:(1)Angular2應用的基礎結構;(2)將應用分為基礎層、公共服務層、業務模塊層3層架構,從而達到各模塊代碼解耦,提高開發效率的作用;(3)分別從模塊、組件安全和服務安全角度說明了應用架構的安全設計,利用Angular2的組件加載機制實現了基于用戶權限認證的組件加載,提高了應用運行的安全性;(4)通過AOT預編譯機制和本地緩存機制優化了應用的加載速度和響應速度。通過以上設計可以有效保障應用安全、提高開發效率、提升用戶體驗。