鑑於微博,QQ,微信等開發平臺的影響,互聯網界的工程師都知道 OAuth 協議,對 Token 存儲用戶信息的機制有所瞭解,卻不多有人說起兩方 OAuth 這個概念。前端
兩方 OAuth
說到 OAuth 協議,潛意識裏都會想到涉及認證,客戶,和服務器,進而是認證服務器,客戶端應用和資源服務器三方。redis
如今通用的 OAuth 協議是 OAuth2.0,是一個互聯網開放受權協議,用於規範資源服務器,客戶端應用,受權服務器三者的職責,實現客戶端應用在不直接獲取到普通用戶的用戶名和密碼的前提下,訪問用戶的私有資源。算法
在實際應用開發過程當中,咱們的應用複雜性沒有達到必定規模時,應用程序只涉及到客戶端 APP 和服務器端中心雲服務的認證和業務處理。咱們能夠對 OAuth2.0 協議進行簡化,演變爲兩方 OAuth。數據庫

上圖[Auth-history.png]是幾個服務器客戶端驗證的階段。後端
OAuth 協議更多的能夠理解爲是一個寬泛的協議,在工程應用方面只關注規範,不要求細節。安全
最初的 OAuth 協議是服務器根據 HTTP 協議頭的 Authorization 字段驗證客戶端身份。服務器
而現在逐漸演變成使用 Token 的方式標記客戶端身份,存儲用戶狀態信息,至於 Token 如何生成,在 HTTP 協議中如何傳輸,並無過多硬性要求。微信
消費者 APP
在 OAuth 協議體系中,消費者是指開發者開發的 APP,這裏的 APP 更是一個廣義的概念,不侷限在安卓和 iOS 應用這兩種類型。PC 網站,移動端 WebView 也被認爲是 APP網絡
服務端,各類雲平臺如何識別這些應用,藉助於應用編號和應用密鑰機制,應用編號就是 APP_ID,或者 APP_KEY,用於惟一識別應用。架構
密鑰就是 APP_SERCRET,用於請求籤名等安全算法的入參,和服務器端驗證的憑據。
「APP_KEY 和 APP_SERCRET 的分配和管理是實現兩方 OAuth 的第一步
讀到這裏,或許你有疑問了,上文說到的不一樣 APP,無非是安卓,iOS,WebView,咱們何不定義不一樣的枚舉來標明不一樣的客戶端,甚至可使用 User-Agent 判斷。
「1 PC,2 安卓 3 iOS 4 微信
這樣的分類能夠解決嗎,答案是很難。
實際上這是兩個概念,從操做系統的角度劃分更多的是一種數據來源渠道的概念,而 APP_KEY 的本質屬性是接入雲端平臺的開發者應用標記。
Token 生命週期
如下是一個簡版的 Token 生命週期模型
分配
Token 由客戶端發起,服務器雲端負責分配,典型的場景,在用戶登陸成功後分配,必定有效期內過時,支持每次請求不一致,token 滑動過時機制。默認 30 分鐘失效。
生成規則
使用用戶標記 userid+應用編號。md5(userid+鹽鑰+時間戳) 鹽值固定。生成規則能夠根據項目個性化調整,Token 值不可逆。
存儲
服務器端 key value 形式存儲到 redis 中,key 爲 token,value 爲加密值 客戶端 Token,按需存儲在本地,後續接口調用時使用。
失效
過時時間內失效,如初始分配 60 分鐘,那 60 分鐘後自動生效。退出時,須要調用接口,刪除 Token。
這裏會引出一個思考
「退出功能須要網絡支持嗎?
這個問題的原因是我發現有些工程師,退出功能是這麼作的,頁面跳轉,清除本地 Token。
Token 表明的是用戶狀態,這種狀態表明的是客戶端與服務端的一種關聯關係,退出功能是切斷這種關聯。
HTTP 是無狀態的,單純的作請求響應,而業務必須是有狀態的,不然業務沒法流轉和推動,這種狀態交給 Token 負責,兩者是如何關聯的。是 Token 設計中須要考量的。
「一個相對完整的 Token 落地機制是實現兩方 OAuth 的第二步
簽名算法
簽名(Sign)用於保證數據的真實性和完整性,從時效,合法性,頻率幾個維度處理。
對全部待簽名參數按照字段名的 ASCII 碼從小到大排序(字典序)後,使用 URL 鍵值對的格式(即 key1=value1&key2=value2…)拼接成字符串 string1。
這裏須要注意的是全部參數名均爲小寫字符,最後加&secret=app_secret;對 string1 做簽名算法,字段名和字段值都採用原始值不進行 URL 轉義。
具體簽名算法爲 sign = md5(string)。除登陸外全部接口,由服務端決定開啓或者關閉簽名驗證。業界叫驗籤。
簽名就用到了 上文提到的APP_SECRET,服務器和客戶端同時使用APP_SECRET 來生成Sign,校驗請求是否合法。

設計要點
採用先後端分離,將接口參數分爲系統級別參數和業務級別參數。系統級參數主要包括 app_key,timestamp,token,os_type,sign,主要置於 HTTP 請求頭位置。業務參數基於業務需求,採用 POST 或者 GET 方法按需傳遞。
檢測請求超時
經過客戶端時間戳 timestamp,來肯定真正的客戶端發起時間。服務器端檢測時間差,客戶端請求時間與服務器時間的差值與超時時間作對比。例如,咱們能夠約定時間差大於 5 分鐘間隔的請求爲無效請求,或者超時請求。
下文中羅列一些這種設計的優點
識別終端
使用 App-Key 的方式識別應用終端,企業內部不一樣的應用,由雲端服務統一管理。
場景 1
進行個性化配置 ,來自於微信公衆號的登陸用戶的過時時長設置爲一天,而來自於 PC 官網的用戶的登陸過時時長設置爲一週。場景 2
公司某個產品線的普通版和定製版的區分,使用 App-Key,對功能的簡易複雜度,收費模式作梯度設置。
場景 3
應用於 SASS 應用識別,多租戶數據隔離,在數據庫對應用數據作隔離。進而爲相關的運營數據分析提供支持。
其它設計規約
1 後臺配置關閉啓用開關,開發階段能夠關閉驗證,建議開啓。
2 啓用驗證後,前端須要有公共方法計算請求籤名。後臺須要增長安全驗證模塊驗證請求合法性,負責登陸過時失效檢測,參數完整性和權限驗證。
3 安全方面關注安全彈性,安全驗證級別經過 timestamp, sign, token 參數,三個維度配合,逐層升級。
經過增長驗證條件和複雜性加強安全級別。安全級別作到合理便可,沒有一律而論。
總結
本文給出了一套基於兩方 OAuth 方式的雲端,客戶端服務設計模型。在應用服務不復雜,業務場景容許的前提下,使用兩個 OAuth 方式。
伴隨着業務發展,能夠逐步演化爲基於三方身份的 OAuth 協議工程實現。
Token 機制和簽名機制也能夠 獨立分層,與業務應用分離,演化爲網關係統。這樣的設計符合架構領域的簡單,演化原則,是一種很實惠的應用架構方案。
本文分享自微信公衆號 - 圖南日晟(tunan_technology)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。