記一次前端適配後臺介面改造的開發小結
在最近工作中,有因後臺介面升級,前端需要配合改造的需求。在改造適配過程中,遇到了問題,再經過多次折騰後,最終調通。事後再回顧整個除錯過程,覺的之前走過一些彎路,在回顧時才看的更加真切,在此需要總結歸納。
問題背景
先描述下問題背景,為簡化後續討論,後續以"查產品資訊"和"查資金"兩個介面為例子,後臺對這兩個介面有升級,具體包括
- "查產品資訊"介面,優化內部實現,認證方式是引數簽名。
- "查資金"介面升級,接口出入參沒變,認證方式改為授權碼,該授權碼由另一個認證服務提供,不同服務的授權碼不一樣。
問題描述
舊版本的流程如下:
前端沒有關心引數簽名細節,將引數一股腦傳給中轉服務,由中轉服務完成對簽名操作,並將簽名值附加在請求最後。
該中轉服務是其他同事負責的,前端沒有關心細節。
後臺改造升級,新的流程如下:
針對"查資金"介面,需要先向認證服務獲取認證碼,該認證碼的許可權很大,為了安全起見,獲取認證碼的操作放到中轉服務中。這個中轉服務是新寫的,考慮到相容對引數簽名接入的相容,對請求引數進行簽名的職責交給前端。
按照上面新流程進行開發,很順利。到聯調階段,發現走引數簽名的方法總是失敗,返回“簽名不通過”的問題。
問題分析流程
根據介面文件的描述,引數簽名的接入需要送兩個特殊的引數:
- RandomKey: 由登陸相關引數拼接而成
- AppKey :由所有url請求引數按照指定規則拼接而成
舊版本的這兩個引數是有中轉服務來拼接,新版改為前端拼接,這裡最初遺漏了對AppKey的處理,後來在新中轉服務中,參照舊版實現,補充對AppKey的處理,發現還是返回“簽名不通過”,這就奇怪了。
在除錯遇到阻礙,無法進行下去時,通過詢問同事以及舊模組的維護人員,靜下心來分析,
舊版本是正常的,新版本返回簽名不通過,新舊版本對接同一個第三方服務,那唯一的可能是新舊版本請求串不一樣。
對比新舊請求url的異同,終於發現突破點,可能是 RandomKey 的問題。
新版本:RandomKey=inputtype%3dC%26inputid%3d123456%26custorgid%3d1000%26orgid%3d1100%26tradenode%3d9501%26ext1%3d0000%26userinfo%3d~~~1100%26authid%ABCDEFD 舊版本:RandomKey=authid%ABCDEFD%26custorgid%3D1000%26ext1%3D1000%26inputid%3D123456%26inputtype%3DC%26orgid%3D1100%26tradenode%3D9501%26userinfo%3D~~~1100
經過對比發現,新舊版本的RandomKey中構成元素是一樣的,唯一區別在於順序。舊版本是按照字母序進行排列,新版本是按照介面文件規定的順序排列。
為什麼按照介面文件規定的順序無法訪問,按照字母序可以訪問呢?舊版本中對random進行字母序排列的依據是什麼?帶著這些疑問,進一步詢問相關人員,發現三個問題:
- 介面文件中對randomkey中順序沒有明確要求,但在驗證時隱含了此要求
- 舊的實現對第三方介面隱含的缺陷進行了相容處理,而沒有對此相容處理做顯式說明,導致後續維護人員踩入同樣的坑
- 舊的實現在對介面簽名時,有一些和前端的約定,比如編碼是由哪一方來做,順序是有哪一方來保證
問題解決方案
分析得到問題根源後,順藤摸瓜,解決方案也就出來了。由前端或者中轉服務來對Random
進行處理,為了後續的靈活性,此處由中轉服務來處理,前端無需關係。
知識點梳理
url編碼知識
url標準規定,url採用ASCII碼,RFC3986文件規定:Url中只允許[0-9a-zA-Z]、“-_.~”4個特殊字元以及所有保留字元(用於分隔不同元件),每個特殊符號有特定含義:
- 冒號":"用於分隔協議和主機
- "/"號用於分隔主機和路徑
- "?"用於分隔路徑和入參
- "="用於鍵值對區分
- "&"區分多個鍵值對
如遇到不安全的字元,使用安全字元來代替。例如中文,上述特殊字元。
為了不對內容有依賴,在拼接url時,需要對path
、key
和value
進行utf8編碼(解決中文傳輸問題),再對進行url編碼(解決key或value中有可能包含URL特殊符號,引起後端解析錯誤)。
base64編碼
base64是將非ASCII資料轉換為ASCII資料的一種方法,編解碼速度快,目的是:
- 相容某些只能處理ASCII字元的系統。
- 解決傳輸裝置(路由器、交換機)對不可見字元處理不一致而引發的問題
- 簡單加密方式
有些Base64編碼方案中包含url中的"+/="字元,採用這種方案,需要先進行base64編碼,再進行url編碼。
如果是針對Url特殊字元改進版的Base64編碼,可不考慮先後順序。
瀏覽器請求
以chrome為例子,當url請求中帶有中文時,例如: “https://baike.baidu.com/item/春節/136876?fr=aladdin” 實際送的是"https://baike.baidu.com/item/春節/136876?fr=aladdin",其中,"春節"兩字的先進行utf8編碼,然後進行url編碼。
對url中的key和value也是同樣的處理方式。
小結
通過本次除錯過程的梳理,有以下幾點經驗和思考:
- 後端在對接第三方服務時,要是發現介面描述不清,在經過溝通後發現需要特殊處理才能跑通,一定要敦促他們完善介面文件,這是最佳選擇。
- 後端在遇到需要特殊處理的地方,要將處理依據以及對接人,明確寫在註釋以及提交記錄上,讓後續維護者瞭解此處的坑。
- 當前端在承接一些後臺職責時,光看介面文件時是不夠的,有時候後臺會對介面中的缺陷進行隱含處理,錯錯得正,給前端造成一種錯覺,覺的按照介面文件來,那就一定沒問題的。
- 前後端聯合開發時,一定要劃分清楚職責並如實記錄,哪裡負責編碼,哪些負責附加欄位等問題,要在概要設計時,就明確下來。
- 編碼問題,不能依著結果是一致就不去編碼,面向邏輯開發,而不是結果開發。不能因為簡單的幾個例子跑對了,就不去管邏輯上可能的遺漏。