背景
一般來說大型互聯網公司會把授權和用戶信息的邏輯放到一個應用中,而這個應用我們統一稱為用戶中心。
用戶中心不關心具體的業務邏輯,只處理用戶信息相關的管理及授權登錄。當第三方應用需要登錄的時候,會把用戶的登錄請求轉發到用戶中心處理,處理完畢后,返回給第三方應用,第三方應用根據對應的憑證登錄到系統內部。
主要功能如下
- 用戶登錄與注冊
- 基本信息查詢與修改
從功能來看,整個用戶中心還是很簡單單,不過其中的邏輯還挺復雜的,比如注冊功能,就要分為手機注冊與郵箱注冊,手機要發送手機驗證碼,郵箱需要發送驗證郵件,點擊郵箱里面的鏈接跳轉並進行后續注冊流程,上面每步都需要業務上重新發送機制。
功能介紹
用戶登錄
在互聯網用戶中心體系中,一般會支持手機、郵箱、帳號、三方登錄。其中三方登錄一般會接入 QQ、微信、微博這三種方式。
密碼登錄
1. 用戶在瀏覽器端填寫 username + password ,然后提交到服務端 2. 服務端拿到用戶提交的 username + password 驗證。 3. 驗證成功后,服務器返回請求,同時將 cookie 寫到對應域
上述流程中,大家肯定會考慮到密碼的安全性,我們到底該怎么做才能防止密碼被泄露?對稱加密還是非對稱加密? 如果是對稱加密,客戶端被黑客反編譯,就能拿到密鑰,那么所有用戶的密碼就會存在非常大的泄露風險?如果是非對稱加密,私鑰要放在哪里才能保證安全?
通用簡單的解決方案: Https + MD5 + 隨機鹽
Https 我就不用在述說了,基本上 Chrome、Firfox 都對不是 Https 的站點進行安全提醒,所以 Https 該上的還是盡快上吧
那如果公司很窮,買不起 Https 證書咋辦呢?那么只能在前端頁面上做點文章。
由於前端代碼暴露在瀏覽器上,我們只能采用不可逆的密碼或者摘要算法,類是與 MD5 / Hash 算法 。如果高級的話,就采用隨機 Salt 來提高攻擊成本,針對不同用戶,加入不同的 Salt,而不是固定鹽的方式。使用這種方式的前提「目前對安全的要求不高」
那我們該如何驗證密碼?客戶端端提交 MD5(password)密碼。服務端通過 MD5 (Salt + MD5(passowrd))的邏輯來計算最終密碼,同時 Salt 只會出現在服務端,且每個用戶采用不同 Salt 的方式來生成。這一系列過程中,都沒有接觸到原始的用戶密碼,如果出現用戶的密碼被劫持的話,只會發生在用戶在提交密碼前截獲,這個也就是為什么需要密碼控件?
三方登錄
當用戶以某種登錄方式成功登錄之后,我們能可以獲取到對應 User 表中的用戶基礎信息,而登錄操作只是為了認證用戶這個過程,無論用本地密碼驗證還是第三方登錄,以上過程本質上都是認證的形式。
所以用戶的信息與登錄的授權其實是獨立開來的,即 uid 與 登錄方式是一對多的關系。比如: 用戶 A 使用「微信」登錄,服務端認證身份后 uid = abc。而下一次用戶 A 使用「微博」登錄,同樣服務端認證出來 uid = abc。
用戶信息表(user_base)只存儲用戶 Profile 相關信息
id | name | city ----+------+----------------- A1 | Tom | 上海 A2 | Jack | 背景
而本地密碼驗證可以當做一種授權方式,可以稱為 local_auth 表
id | user_id | password ----+---------+---------- 1 | A1 | qazwsx 2 | A2 | edcrfv
而通過微博登錄就可以視作為另外一種登錄方式,稱為 weibo_auth 表
id | user_id | weibo_id | weibo_access_token | weibo_expires
----+---------+----------+--------------------+---------------
1 | A1 | W-qaz | xxxxxxxxxx | 604800
2 | A2 | W-wsx | xxxxxxxxxx | 604800
最后,如果還要增加一種登錄方式的話,可以直接添加一直 xx_auth 表來存儲用戶認證信息,大大提高了我們授權方式的靈活性