­

IM開發基礎知識補課(七):主流移動端帳號登錄方式的原理及設計思路

  • 2019 年 12 月 13 日
  • 筆記

本文引用了「低調的碼農」原創文章「多賬戶的統一登錄」一文的部分內容,感謝原作者的無私分享。

1、引言

在即時通訊網經常能看到各種高大上的高並發、分散式、高性能架構設計方面的文章,平時大家參加的眾多開發者大會,主題也都是各種高大上的話題——什麼5G啦、AI人工智慧啦、什麼阿里雙11分分鐘多少萬QPS高並發等等。

但實際上,對於普通的開發者(包括IM開發人員)來說,多數公司、多數團隊也都是干著默默無聞、平淡無奇的產品開發,並沒有那麼多高並發、高大上的事情可以做。

就拿一個IM系統來說,無論你的架構設計考慮了多少分散式、高吞吐、高可用,所有這些事情只要落地,那編碼的第一件事情就是要實現幾乎所有資訊系統都要面對的任務——如何設計帳號登錄功能?

本文將分享幾種典型的移動端帳號登陸方式的技術原理,以及設計思路,理解後,完全可以快速實施於你的各種應用系統(並不限於IM系統)中。本文閱讀對像主要為剛入門的開發人員,請程式老司機們嘴下留情哦。

通過本篇文章, 你可以學到:

1)主流帳號登陋技術方案細節; 2)相應的表設計; 3)相應的流程設計。

通過本篇文章, 你無法學到:

與其他原理性的文章一樣,本篇不涉及具體程式碼實現細節(對於程式設計師來說,只要思路搞通,程式碼咋寫都不會太爛,大家應該都有體會)。

學習交流:

– 即時通訊/推送技術開發交流5群:215477170[推薦] – 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM

(本文同步發佈於:http://www.52im.net/thread-2863-1-1.html

2、IM開發乾貨系列文章

本文是系列文章中的第20篇,總目錄如下:

IM消息送達保證機制實現(一):保證在線實時消息的可靠投遞》 《IM消息送達保證機制實現(二):保證離線消息的可靠投遞》 《如何保證IM實時消息的「時序性」與「一致性」?》 《IM單聊和群聊中的在線狀態同步應該用「推」還是「拉」?》 《IM群聊消息如此複雜,如何保證不丟不重?》 《一種Android端IM智慧心跳演算法的設計與實現探討(含樣例程式碼)》 《移動端IM登錄時拉取數據如何作到省流量?》 《通俗易懂:基於集群的移動端IM接入層負載均衡方案分享》 《淺談移動端IM的多點登陸和消息漫遊原理》 《IM開發基礎知識補課(一):正確理解前置HTTP SSO單點登陸介面的原理》 《IM開發基礎知識補課(二):如何設計大量圖片文件的服務端存儲架構?》 《IM開發基礎知識補課(三):快速理解服務端資料庫讀寫分離原理及實踐建議》 《IM開發基礎知識補課(四):正確理解HTTP短連接中的Cookie、Session和Token》 《IM群聊消息的已讀回執功能該怎麼實現?》 《IM群聊消息究竟是存1份(即擴散讀)還是存多份(即擴散寫)?》 《IM開發基礎知識補課(五):通俗易懂,正確理解並用好MQ消息隊列》 《一個低成本確保IM消息時序的方法探討》 《IM開發基礎知識補課(六):資料庫用NoSQL還是SQL?讀這篇就夠了!》 《IM里「附近的人」功能實現原理是什麼?如何高效率地實現它?》 《IM開發基礎知識補課(七):主流移動端帳號登錄方式的原理及設計思路》(本文)

3、最經典的用戶名密碼註冊登陸方式

一個典型的用戶名密碼註冊登陸功能類似於下面這樣:

這種帳號登陸方式很經典也很常用,先註冊、再進行登錄,尤其在老一點的CMS系統、網站系統、聊天應用中都能找到這個影子。

它的技術原理流程圖如下:

如上圖所示,詳細的流程說明如下:

1)前端將用戶名、密碼發送到伺服器,伺服器進行常規的判斷,判斷用戶名、密碼長度是否滿足,用戶名是否重複等條件,條件不通過直接返回對應錯誤碼給到前端,這裡密碼欄位,為了防止傳輸過程中被截胡,建議加密再上傳,我們的傳輸密碼默認都是會進行一個md5加密,然後記錄到資料庫再進行一層加密,就算是脫庫也沒事,密碼不要明文存儲。

2)校驗通過後,就將用戶名密碼寫入資料庫,並進行後面積分發放等操作,這裡不展開。

3)現在進行登錄,前端將用戶名,密碼發送給到服務端,服務端首先會校驗登錄次數是否超過設置的閾值,如果超過只能繼續等待被關小黑屋。

4)如果未超過繼續登錄邏輯,判斷用戶名、密碼是否正確,不正確密碼則進行閾值的判斷,如果超過則關小黑屋,記住小黑屋必須設置過期時間,要不然就會永久關上了,這個可以用redis的過期來做。

5)登錄成功後進行後續的一切後置邏輯,比如加積分。。。等操作。

這種經典的註冊登陸方式,具體怎麼設計就不在這裡贅述了,誰都懂。

4、現今最主流的手機號註冊登陸方式

4.1 基本原理

典型的手機號註冊登陸功能類似於下圖:

典型的手機號註冊技術原理流程圖如下:

如上圖所示,詳細的流程說明如下:

1)首先輸入手機號:然後發送到服務端,服務端將手機號記錄在我們資料庫中,然後生成隨機驗證碼,並將手機號和驗證碼綁定到一個redis裡面,然後記錄過期時間,這個過期時間一般是10分鐘左右,這就是我們一般手機驗證碼的有效期;

2)手機接收到手機簡訊後:那麼就在介面填寫驗證碼發送服務端,服務端收到驗證碼後就會在redis裡面查詢到這個手機號對應的驗證碼,失敗就返回錯誤碼。

3)成功後:就進行登錄操作。

這裡看起來沒有明確的註冊登錄操作,其實在發送手機號碼就可以認為是一個常規的註冊,然後後面的驗證碼輸入就是一個登陸操作。

但這種區別於常見的用戶名密碼註冊方式,是沒有密碼的的。

問: 那我要密碼咋辦? 答: 在後續產品裡面增加一個手機號碼密碼補錄的功能即可,這也是現在很常規的手法,但是現在移動互聯網大爆炸時代,密碼已經顯得不是那麼重要了,反正我從來記不住密碼,如果手機號碼能操作的app,絕對不用密碼來操作。

4.2 具體的資料庫設計

表結構:

說明:

這裡只是單純說明需要用到的數據,沒有擴展具體場景,這個表結構能夠滿足上面兩個方案的設計。

5、一種輔助的登陸方式:第3方帳號登陸

5.1 基本原理

現在很多應用為了降低新用戶的使用門檻,都會對接第3方帳號進行登陸(比如:用微訊號登陸、QQ號登陸、微博帳號登陸等)。

這裡我以QQ的開放平台登錄邏輯為例進行講解。

某團外賣的QQ帳號登陸功能如下圖:

我們先來一波時序圖:

時序流程詳細說明:

1)客戶端自己調起登錄的介面,進行輸入用戶名、密碼,這裡的是第三方的用戶名,密碼,登錄成功後,會返回access_token openid expire_in,這過程會使用到oauth2.0,不過在sdk裡面進行內置回調獲取了,後面我們會說明我們自身實現的oauth2.0;

2)客戶端拿到access_token、openid、login_type(qq、wechat…)請求應用伺服器,應用伺服器拿到這些數據後就會根據對應的login_type去對應的用戶中心進行access_token和openid進行校驗。校驗不通過則返回對應錯誤碼;

3)校驗通過後就會判斷本地是否有這個login_type和openid是否存在,不存在則進行獲取遠程的用戶名、頭像等基礎資訊來作為本地基礎數據,並且返回code值;

4)如果已經存在,那就是進行登錄操作,返回code值;

5)客戶端拿到code值後進行token值的換取,這個完全遵照oauth2.0的協議來走的,後續每次請求必須帶上token,token值在服務端的時間比較久,因為我們想要做的是那種永不下線的操作,所以每次請求我們都將token過期時間進行累加。

想要深入了解第3方帳號登陸,可以讀讀這兩篇:《第三方登錄:QQ登錄接入指南》、《第三方帳號登錄功能接入完全流程》。

5.2 具體的資料庫設計

表結構:

對於讀者的建議,我這裡做一下資料庫的整理。

用戶基礎表(users):

用戶驗證關聯表(user_auth_rel):

本地用戶表(user_local_auth):

第三方用戶表(user_third_auth):

表結說明:

1)users表只是單純針對我們業務側的登錄,主要是做自身業務的oauth2.0業務;

2)user_local_auth是做自己用戶名、密碼登錄,手機號碼登錄資訊記錄;

3)user_third_auth是我們第三方用戶體系的數據記錄;

4)user_auth_rel是用來關聯我們users表與user_local_auth、user_third_auth;

5)整個設計理念就是將自建用戶與第三方在存儲上區分,這在架構演進上也是合乎情理的,開始用戶體系大多自建,而後才是對外接入。

6、本文小結

總的來講,帳號註冊登錄功能在一般的系統里都是入口功能,一般情況下都不會太複雜。

對於第三方用戶的接入技術,也同樣比較簡單,我文章里設計多一個user_thirds是可以支援足夠多的第三方接入,當然一般我們也就兩三個登錄就好,太多登錄方不僅自身維護成本,介面擺盤也不好看不是。

希望大家能夠通過以上學習,能夠對於賬戶註冊登錄有一個比較好的認知,文章里設計方案不包含分表分庫、沒有服務化,就是簡單直接的設計,當然用戶量和需要的不一樣,在這個基礎上還要加很多東西,謝謝大家閱讀。