Api接口通用安全策略及實現-OSS.Core
這篇文章一直說寫,遲遲沒有動手,這兩天看到一些應用接口數據被別人爬蟲、短信接口被人高頻率請求攻擊等案列,感覺簡單概述分享一下接口安全驗證還是有必要的。畢竟當下基本都以客戶端應用為主,如果前期疏忽,發布之後的維護升級等將會有很大的麻煩。這裏我將主要圍繞以下幾個方面:
1. 基礎的安全策略
2. Restful安全實現方式介紹
3. OSS.Core實現案例
4. OSS.Core接口參數規範
一. 基礎的安全策略
這裏討論只針對應用本身,像Https或者防火墻等第三方支持不在此討論範圍。
對於一個接口項目來說,安全策略我個人認為主要分兩塊:1. 接口驗證模塊 2. 用戶驗證模塊
1. 接口驗證模塊
這個模塊是對整個接口安全層面負責。對於接口安全而言,特別是客戶端接口,是直接暴露在整個互聯網中的,我們首先要保證的就是不會被別人冒名請求我們的接口數據。經常使用的就是簽名驗證,在接口正常的數據傳輸之外,傳遞額外的約定加密簽名信息等,來過濾非授權的接口請求。
這裏可以舉一個去年我遇到的典型案列,當時有個外賣的站點短信發送接口沒有添加任何驗證,接口地址還寫在了頁面上,可想而知後果有多麽嚴重,網絡上的很多短信轟炸機用的就是這些接口,這裏給一張當時發現時測試的截圖:
當然簽名校驗只是最基礎的安全校驗,如果再配合IP限流等校驗措施效果更佳!
2. 用戶授權驗證模塊
這個模塊主要是對用戶個體負責,上一步主要是在一定程度上過濾一些非自身應用接口請求。但是應用本身出了問題,例如漏洞或者被反編譯等,又或者是人員流動造成的秘鑰泄露,又如何保證接口的真實用戶數據不被輕易篡改。
對於這個問題,我們可以獨立一個用戶驗證模塊,核心思路就是通過給每個登錄用戶頒發token(可以通過用戶編號加密,或者編號+時間戳),對用戶相關的操作通過token驗證,用戶主鍵信息不通過接口明文傳送,在服務端通過token解密獲取。token的加解密過程都在服務端完成,和簽名驗證模塊獨立。
這兩個模塊也可以通過下邊的簡單時序圖了解相關分工:
二. Restful接口下安全實現方式介紹
上邊介紹了一個基礎的接口驗證步驟,這邊我以常見的http接口協議來簡單介紹下實現過程:
1. 簽名驗證
這個主要是通過對每次請求通過參數和隨機數的排序組合生成唯一的簽名【sign】信息,方式多種多樣,這裏我介紹一種通用做法,如果你對第三方網站簽名驗證比較熟悉可以跳過。
這裏因為一個接口項目可能會給對個應用提供數據服務,我們給每個應用頒發對應的appid和appsecret信息。
第一步,在正常傳遞的參數外,添加appid,timespan(當前時間戳)參數,把當前參數集合中值不為空的參數按照參數名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串str,同時需要註意一下幾點。
- 參數名ASCII碼從小到大排序(字典序)
- 參數的值為空不參與簽名
- 參數名區分大小寫
第二步,將得到str使用簽名算法,生成sign(主要看和服務器約定的加密算法,一般使用單向簽名算法即可),一下是兩種常見加密算法
1. 使用MD5
在str後追加 &appsecret=xxx 後再進行md5 加密,即 sign = md5(str&appsecret=xxx)
2. 使用SHA1
因為sha1本身支持加鹽操作, 直接使用 appsecret加密 str ,即 sign=sha1(str, appsecret)
第三步: 傳遞內容 str&sign=xxxx 到服務端。
以上是一個基本的簽名實現過程,當然具體的實現可以根據實際情況各自調整,比如簽名信息也可以放在請求header中,參數格式也可以是json等,重要的是需要保證:每次請求簽名不會相同
2. 用戶授權驗證實現
這個大家可以參考最近比較流行的 jwt 協議等實現,主要思路是用戶授權後,服務端頒發token返回給客戶端,在請求相關授權接口時附帶token即可。
這裏加密算法需要使用雙向加密算法,然後服務端在處理請求時,攔截並解密相關信息,保存在上下文中。
三. OSS.Core實現案例
1. 簽名驗證:
在OSS.Core項目,我把簽名相關驗證信息放置在請求頭(httpheader)中,通過自定義AuthorizeSignMiddleware中間件在程序入口處進行攔截,主要包含以下參數(實現代碼詳見GitHub):
如果你想了解詳細排序加密等處理,可參見OSS.Common中的SysAuthorizeInfo
2. 用戶驗證模塊:
主要通過自定義Attribute註冊實現,代碼詳見 GitHub中AuthorizeMemberAttribute, 同時我會將當前用戶信息保存在一個 AsyncLocal 變量中,詳細代碼參見OSS.Common中的MemberShiper
四. OSS.Core接口參數規範
所有的接口信息中,我會定義套全局錯誤碼,所有的接口返回信息中都會包含ret標識,來返回當前接口的正常與否,比如:如果ret=1423時表示非法應用來源,ret=1425需要去獲取授權驗證token,當然每個接口也可以自定義其特有的局部錯誤碼。
全局錯誤碼詳見:Github 下 ResultTypes
同時,接口請求頭中AppSource,AppVersion,AppClient 參數必填,來保證後續的活躍度,用戶註冊,訂單分布等情況統計。
Api接口通用安全策略及實現-OSS.Core