多賬號統一登陸,賬號模塊的系統設計

點擊上方 "程序員小樂"關注公眾號, 星標或置頂一起成長

每天早上8點20分, 第一時間與你相約

每日英文

There are some things that we have no choice but to accept, there are some people who we have no choice but to let go, and there are some roads that after we've chosen them, there's no looking back.

有些事,發生了就只能接受。有些人,失去了就只有放手。有些路,選擇了就沒得回頭

每日掏心話

淡然面對幸運,笑著面對不順,這才是人生。很多時候,我們是在毫無防備中受傷的,一句話,一件事,都有可能讓牽手成為陌路。

鏈接:dustyblog.cn

多賬號統一登陸,賬號模塊的系統設計

程序員小樂(ID:study_tech)第 635 次推文 圖片來自網絡

往日回顧:2019年9月全國程序員最新工資統計, 看看你拖後腿了嗎?

00 前言

現在幾乎大部分的 App 都支持使用多個第三方賬號進行登錄,如:微信、QQ、微博等,我們把此稱為多賬號統一登陸。而這些賬號的表設計,流程設計至關重要,不然後續擴展性賊差。

本文不提供任何代碼實操,但是梳理一下博主根據我司賬號模塊的設計,提供思路,僅供參考。

01 自建的登陸體系

1.1.1 手機號登陸註冊

該設計的思路是每個手機號對應一個用戶,手機號為必填項。

流程:

  • 首先輸入手機號,然後發送到服務端。先判斷該手機號是否存在賬號,如果沒有,就會生成隨機驗證碼,將手機號和驗證碼綁定到 Redis中,並設置一定的過期時間(過期時間一般是5分鐘,這就是我們一般手機驗證碼的有效期),最後將驗證碼通過短信發送給用戶。

  • 用戶接收到驗證碼後,在界面填寫驗證碼以及密碼等基礎信息,然後將這些數據發送服務端。服務端收到後,先判斷在 Redis裡面這個手機號對應的驗證碼是否一致,,失敗就返回錯誤碼,成功就給用戶創建一個賬號和保存密碼。

  • 註冊成功後,用戶即可通過自己的 手機號+密碼進行登陸。

問題:

  • 用戶體驗差,需要完成獲取驗證碼,填寫驗證碼/密碼/用戶名等諸多的信息完成註冊,然後才能使用;

  • 容易遺忘密碼,遺忘後,只能通過忘記密碼來重新設置密碼。

1.1.2 優化註冊登陸

該方案的思路是弱化密碼的必填性,即無論用戶是否註冊過,可通過 手機號+驗證碼 直接進行登陸(保留 手機號+密碼登錄的方式)。

流程:

  • 輸入手機號,然後發送到服務端。服務端生成隨機驗證碼,將手機號和驗證碼綁定到 Redis中,並設置一定的過期時間(過期時間一般是5分鐘,這就是我們一般手機驗證碼的有效期),最後將驗證碼通過短信發送給用戶。

  • 用戶接收到驗證碼後,在界面只需填寫收到的驗證碼,提交到服務端。服務端收到後,先判斷在 Redis裡面這個手機號對應的驗證碼是否一致,失敗就返回錯誤碼,成功就直接登錄。如果是老用戶,直接拉取用戶信息;如果是新用戶,則提示他可以完善用戶信息(不強制)。

  • 用戶通過 手機號+驗證碼登錄後,也可選擇設置密碼,然後就可以通過 手機號+密碼的方式登錄,即:密碼是非必填項。

用戶表設計:

id

user_name

user_password

user_mobile

state

more

用戶id 用戶名 用戶密碼 手機號碼 賬號狀態 其他信息

1.2 引入第三方賬戶方案

1.2.1 微博登錄

進入 Web2.0 時代 ,微博開放了第三方網站登錄, 產品說, 這個我們得要, 加個用微博帳號就能登錄我們的 App吧,而且得和我們自己的用戶表關聯。

流程:

  • 客戶端調用微博登錄的界面,進行輸入用戶名、密碼,登錄成功後,會返回 access_token,通過 access_token調取 API接口獲取用戶信息。

  • 服務端通過用戶信息在我們用戶表創建一個賬號,以後,該第三方賬號即可通過該微博賬號直接進行登陸。

微博用戶信息表設計:

id

user_id

uid

access_token

主鍵id 用戶id 微博唯一id 授權碼

1.2.2 噩夢來臨

緊接著, QQ又開放用戶登錄了, 微信開放用戶登錄了,網易開發用戶登錄了。。。。。。一下子要接入好多家第三方登錄了, 只能按照 “微博用戶信息表” 新建一個表,重寫一套各個第三方登錄。

02 優化賬號體系

2.1 原賬號體系分析

  • 自建登陸體系:無論 手機號+密碼 , 還是 手機號+驗證碼 , 都是一種 用戶信息+密碼 的驗證形式;

  • 第三方登錄:也是 用戶信息+密碼 的形式, 用戶信息即第三方系統中的 ID(第三方系統中的唯一標識), 密碼即 access_token, 只不過是一種有使用時效定期修改的密碼。

2.2 新的賬號體系

2.2.1 數據表設計

用戶基礎信息表:

id

nickname

avatar

more

用戶id 暱稱 頭像 其他信息

id

user_id

identity_type

identifier

credential

主鍵id 用戶id 登錄類型(手機號/郵箱) 或第三方應用名稱 (微信/微博等) 手機號/郵箱/第三方的唯一標識 密碼憑證 (自建賬號的保存密碼, 第三方的保存 token)

說明:

  • 用戶表分為 用戶基礎信息表 + 用戶授權信息表;

  • 用戶信息表不保存任何密碼, 不保存任何登錄信息(如用戶名, 手機號, 郵箱), 只留有暱稱、頭像等基礎信息; 所有和授權相關,都放在用戶信息授權表, 用戶信息表和用戶授權表是一對多的關係。

2.2.2 登錄流程

  • 手機號+驗證碼

沿用之前的方案。

  • 郵箱/手機號+密碼:

用戶填寫 郵箱/手機號+密碼; 請求登錄的時候, 先判斷類型, 如手機號登錄為例:

使用 type='phone' 結合 identifier='手機號' 查找, 如有, 取出並判斷 password_hash(密碼)是否和該條目的 credential 相符, 相符則通過驗證, 隨後通過 user_id 獲取用戶信息;

查詢 type='weixin' 結合 identifier='微信 openId', 如果有記錄, 則直接登錄成功, 並更新 token; 假設與微信服務器通信不被劫持的情況下無需判斷憑證問題。

2.2.3 優缺點

優點:

  • 登錄類型無限擴展, 新增登錄類型的開發成本顯著降低;

  • 原來條件下, 應用需要驗證手機號是否已驗證和郵箱是否已驗證, 需要相對應多一個字段如 phone_verified 和 email_verified, 如今只要在 用戶授權信息表 表中增加一個統一的 verified字段, 每種登錄方式都可以直觀看到是否已驗證情況;

  • 在 用戶授權信息表 添加相應的時間和 IP 地址, 就可以更加完整地跟蹤用戶的使用習慣, 比如:已經不使用微博登錄兩年多, 已經綁定微信 300天;

  • 如果你說郵箱和手機號就是用戶信息的組成部分, users 表儘管拓展, users 表裡依然有email , phone , 但他們僅僅作為“展示用途”,和暱稱,頭像或者性別這些屬性沒有本質區別;

  • 可按需綁定任意數量的同類型登錄方式, 即一個用戶可以綁定多個微信, 可以有多個郵箱, 可以有多個手機號。當然你也可以限制一種登錄方式只有一條記錄;

缺點 :

  • 用戶同時存在郵箱、用戶名、手機號等多種站內登錄方式時, 改密碼時必須一起改, 否則就變成了 郵箱+新密碼, 手機號+舊密碼都可以登錄, 肯定是很詭異的情況;

  • 代碼量增加了, 有些情況下邏輯判斷增加了, 難度增大了; 舉個例子, 無論用戶是否已登錄, 無論用戶是否已註冊過, 都是點擊同一鏈接前往微博第三方授權後返回, 可能出現幾種情況:

  • 該微博在本站未註冊過, 很好, 直接給他註冊關聯並登錄;

  • 該微博已經在本站存在, 當前用戶未登錄, 直接登錄成功;

  • 該微博未在本站註冊, 但當前用戶已經登錄並關聯的是另一個微博帳號, 作何處理取決於是否允許綁定多個微博帳號;

  • 該微博未在本站註冊過, 當前用戶已登錄, 嘗試進行綁定操作;

  • 該微博已經註冊, 用戶又已使用該帳號登錄, 為何他重複綁定自己;

  • 該微博已經在本站存在, 但當前用戶已經登錄並關聯的是另一個微博帳號, 作何處理?

03 一鍵登錄

3.1 背景

回顧一下 手機號+驗證碼 的登錄方式:

  • 輸入手機號、等待驗證碼短信、輸入驗證碼、點擊登錄。整個流程走完可能需要 20 秒以上,操作也比較繁瑣;

  • 它是依賴短信網絡的,因為如果收不到短信,也就登錄不了了。

  • 從安全角度考慮,還存在驗證碼洩漏的風險。如果有人知道了你的手機號,並且竊取到了驗證碼,那他也能登錄你的賬號了。

但回過頭來想一下,為什麼我們需要驗證碼?驗證碼的作用就是確定這個手機號是你的,那除了使用短信,是否還有別的方式對手機號進行認證?

  • 如果能獲取到當前使用的手機號,就能對用戶輸入的號碼進行驗證了。但出於安全考慮,客戶端是無法直接獲取到手機號的,運營商則可以通過 SIM 卡數據查詢到。

  • 現在運營商已經開放了相關的能力,現在我們可以在用戶輸入手機號後,通過調用運營商的接口,判斷用戶輸入的手機號是否和本地號碼一致。這樣一來,用戶就省去了等待驗證碼短信、輸入驗證碼的過程,也不受短信網絡的限制,簡化了登錄流程。

  • 但再進一步想,如果運營商可以把當前的號碼直接返回給我們,而不只是用於驗證,那用戶連手機號都不需要填了。

這就是該部分的主角:一鍵登錄。

3.2 本機號碼認證

獲取到當前手機使用的手機卡號,直接使用這個號碼進行登錄,這就是一鍵登錄。

這種登錄方式的好處是顯而易見的。它可以更方便、快捷地完成註冊、登錄流程,將原本可能需要 20 秒的流程,縮短到了 2 秒左右,很大程度上提升了登錄的用戶體驗。

主要步驟如下:

  • SDK 初始化:調用 SDK 的初始化方法,傳入項目在平臺上的 AppKey 和 AppSecret。

  • 喚起授權頁:調用 SDK 喚起授權接口。SDK 會先向運營商發起獲取手機號驗碼的請求,請求成功後跳轉到授權頁。授權頁會顯示手機號掩碼以及運營商協議給用戶確認。

  • 同意授權並登錄:用戶同意相關協議,點擊授權頁面的登錄按鈕,SDK 會請求本次取號的 token,請求成功後將 token 返回給客戶端。

  • 取號:將獲取到的 token 發送到我們自己的服務器,由服務器攜帶 token 調用運營商一鍵登錄的接口,調用成功就返回手機號碼了。服務器用手機號進行登錄或註冊操作,返回操作結果給客戶端,完成一鍵登錄。

目前阿里雲已經提供了該方式並可兼容三大運營商的號碼,詳見 阿里雲SDK:

https://help.aliyun.com/document_detail/121113.html

04 小結

博主看來,沒有最好的方案,選擇適用當前系統的設計即可。不要深究孰優孰劣,鞋合不合腳,只有腳知道。

歡迎在留言區留下你的觀點,一起討論提高。如果今天的文章讓你有新的啟發,學習能力的提升上有新的認識,歡迎轉發分享給更多人。

歡迎各位讀者加入程序員小樂技術群,在公眾號後臺回覆“加群”或者“學習”即可。

猜你還想看

阿里、騰訊、百度、華為、京東最新面試題彙集

不會SQL注入,連漫畫都看不懂了

中美互聯網科技公司對比圖!你有的,我們也有!

Redis基礎都不會,好意思出去面試?

理解MySQL鎖和事務,看這篇如何?

團隊中的 Git 實踐

關注「程序員小樂」,收看更多精彩內容

嘿,你在看嗎?


分享到:


相關文章: