前端處理過程中常常發現接口定義不符合使用者操作流程,AJAX 異步請求過多等問題
采用基于 Token 的認證就意味着後端的認證部分需要重寫
從後端的角度來看,重點關注的是資料完整、有效、安全。沖突在于雙方關注點不同,資訊不對稱,還各有私心
就形式上來說,Web API 可以定義成 REST,也可以是 RPC,隻要前後端商議确定下來就行。更重要的是在輸入參數和輸出結果上,最好一開始就有相對固定的定義,這往往取決于前端架構或采用的 UI 架構。
常見請求參數的資料形式有如下一些:
鍵值對,用于 URL 中的 QueryString 或者 POST 等方法的 Payload
XML/JSON/...,通常用于 POST 等方法的 Payload,也可以使用 multipart 傳遞
ROUTE,由後端路由解析 URL 取得,在 RESTful 中常用
而伺服器響應的資料形式就五花八門各式各樣了,通常一個完整的響應至少需要包含狀态碼、消息、資料三個部分的内容,其中
狀态碼,HTTP 狀态碼或響應資料中特定的狀态屬性
消息,通常是放在響應内容中,作為資料的一部分
資料,根據接口協定,可能是各種格式,目前最流行的是 JSON
我們在實踐中使用 JSON 形式,最初定義了這樣一種形式
{
"code": "number",
"message": "string",
"data": "any"
}
code 主要用于指導前端進行一些特殊的操作,比如 0 表示 API 調用成功,非0 表示調用失敗,其中 1 表示需要登入、2 表示未擷取授權……對于這個定義,前端拿到響應之後,就可以在應用架構層進行一些正常處理,比如當 code 為 1 的時候,彈出登入視窗請使用者在目前頁面登入,而當 code 為 2 的時候,則彈出消息提示并後附連結引導使用者擷取授權。
<a href="http://blog.51cto.com/jamesfancy/2061675">http://blog.51cto.com/jamesfancy/2061675</a>
前後分離模型之封裝 Api 調用
一開始這樣做并沒有什麼問題,直到前端架構換用了 jQuery EasyUI。以 EasyUI 為例的好多 UI 庫都支援為元件配置資料 URL,它會自動通過 AJAX 來擷取資料,但對資料結構有要求。如果仍然采用之前設計的響應結構,就需要為元件定義資料過濾器(filter)來處理響應結果,這樣做寫 filter 以及為元件聲明 filter 的工作量也是不小的。為了減少這部分工作量我們決定改一改接口。
新的接口是一種可變結構,正常情況下傳回 UI 需要的資料結構,出錯的情況則響應一個類型于原定結構的資料結構:
"error": {
"identity": "special identity string",
對于新響應資料結構,前端架構隻需要判斷一下是否存在 error 屬性,如果存在,檢查其 identity 屬性是否為指定的特殊值(比如某個特定的 GUID),然後再使用其 code 和 message 屬性處理錯誤。這個錯誤判斷過程略為複雜一些,但可以由前端應用架構統一處理。
如果使用 RESTful 風格的接口,部分狀态碼可以用 HTTP 狀态碼代替,比如 401 表示需要登入,403 就可以表示沒有獲得授權,500 表示程式處理過程中發生錯誤。當然,雖然 HTTP 狀态碼與 RESTful 風格更配,但是非 RESTful 風格也可以使用 HTTP 狀态碼來代替 error.code。
使用者認證
認證方案很多,比如 Cookie/Session 在某些環境下仍然可行、也可以使用基于 Token 和 OAuth 或者 JWT,甚至是自己實作基于 Token 的認證方式。
基于 Cookie/Session 的認證方案
然後一般前後端分離的開發方式,不管是開發階段還是釋出階段,不同源的可能性占絕大比例,是以認證方案通常會使用與 Cookie 無關的方案。
基于 OAuth 的認證方案
目前各大網站的開放式接口都是 SOA 架構,如果把這些開放式接口看作提供服務方(服務端),而把使用這些開放式接口的應用看作用戶端,那麼就可以産生這樣一種和前後分離對應的關系:
前端 ⇌ 用戶端
⇣
基于 OAuth 的認證)
⇡
後端 ⇌ 服務端
是以,開放式接口廣泛使用的 OAuth 方案用于前後分離是可行的,但在具體實施上卻并不是那麼容易。尤其是在安全性上,由于前端是完全暴露在外的,與 OAuth 通常實施的環境(後端⇌服務端)相比,要注意的是首次認證不是使用已注冊的 AppID 和 AppToken,而是使用使用者名和密碼。
基于 Token/JWT 的認證方案
雖然這個方案放在最後,但這個方案卻是目前前後端分離最适合的方案。基于 Token 的認證方案,各種讨論由來已久,而 JWT 是相對較為成熟,也得到多數人認可的一種。從 jwt.io 上可以找到各種技術棧的 JWT 實作,應用起來也比較友善。
話雖如此,JWT 方案和以前使用的 Cookie/Session 在處理上還是有較大的差别,需要一定的學習成本。有人擔心 JWT 的資料量太大。這确實是一個問題,但是硬體并不貴,4G 也開始進入不限流量階段,一般應用中不用太在意這個問題。
前後分離的測試
前後分離之後,前端的測試将以使用者體驗測試和內建測試為主,而後端則主要是進行單元測試和 Web API 接口測試。與一體化的 Web 應用相比,多了一層接口測試,這一層測試可以完全自動化,一旦完成測試開發,就能在很大程度上控制住業務處理和資料錯誤。這樣一來,內建測試的工作量會相對單一也容易得多。
前端測試的工作相對來說減輕不了多少,前後分離之後的前端部分承擔了原來的內建測試工作。但是在假設 Web API 正确的情況下進行內建測試,工作量是可以減輕不少的,用例可以隻關注前端體驗性的問題,比如呈現是否正确,跳轉是否正确,使用者的操作步驟是否符合要求以及提示資訊是否準确等等。
對于使用者輸入有效性驗證這部分工作在項目時間緊迫的情況下甚至都可以完全抛給 Web API 去處理。不管是否前後端分離,Web 開發中都有一個共識:永遠不要相信前端!既然後端必須保證資料的安全性和有效性,那麼前端省略這一步驟并不會對後端造成什麼實質性的威脅,最多隻是使用者體驗差一點。但是,如果前後端都要做資料有效性驗證,那一定要嚴格按照文檔來進行,不然很容易出現前後端資料驗證不一緻的情況(這不是前後分離的問題,一體化架構同樣存在這個問題)。
小結
總的來說,前後分離所帶來的好處還是很明顯的。但是具體實施的時候需要一個全新的思考方式,而不是基于原有一體化 Web 開發方式來進行思考。前後分離的開放方式将開發人員從複雜的技術組合中解放出來,大家都可以更專注于自己擅長的領域來進行開發,但同時也對前後端團隊的溝通交流提出了更高的要求,前後端團隊必須要一同設計出相對穩定的 Web API 接口(這部分工作其實不管是否前後端分離都是少不了的,隻是前後分離的架構對此要求更高,更明确地要求接口不隻存在于人的記憶中,更要文檔化、持久化)。
2017-07

本文轉自 liqius 51CTO部落格,原文連結:http://blog.51cto.com/szgb17/2063541,如需轉載請自行聯系原作者