用戶表設計摘錄

說起用戶表,大概是每個應用/網站立項動工(碼農們)考慮的第一件事情。用戶表結構的設計,算是整個后臺架構的基石。如果基石不穩,待到后面需求跟進了發現不能應付,回過頭來反復修改用戶表,要大大小小作改動的地方也不少。與其如此,不妨設計用戶表之初就考慮可拓展性,爭取不需要太多額外代價的情況下一步到位

示例一:
本例使用兩個表 passport,profile 完成網站會員系統。
首先說說passport表,你也要以使用user或member等等命名,這個表設計盡可能地簡單,不要使用過多字段。僅保存登錄所必須用到的字段,如user,password,nickname,email... 登錄帳號和密碼做復合索引。
然后是profile表,這個表與passport是1:1關系,保存用戶詳細信息
這樣設計可以保證海量用戶登錄時的速度。


users表

示例二:
無論username+password,還是phone+password,都是一種用戶信息+密碼的驗證形式;再來理解第三方登錄,其實它也是用戶信息+密碼的形式,用戶信息即第三方系統中的ID(第三方登錄一定會給一個在他們系統中的唯一標識),密碼即access_token,只不過是一種有使用時效定期修改的密碼。所以我們把它抽象出了用戶基礎信息表加上用戶授權信息表的形式。

用戶基礎信息表 users
id
nickname
avatar

用戶授權信息表 user_auths
id
user_id
identity_type 登錄類型(手機號 郵箱 用戶名)或第三方應用名稱(微信 微博等)
identifier 標識(手機號 郵箱 用戶名或第三方應用的唯一標識)
credential 密碼憑證(站內的保存密碼,站外的不保存或保存token)

這個系統最大的特色就是,用戶信息表不保存任何密碼,不保存任何登錄信息(如用戶名、手機號、郵箱),只留有昵稱、頭像等基礎信息。所有和授權相關(且基本前端展示無關的),都放在用戶信息授權表,用戶信息表和用戶授權表是一對多的關系。說起來太抽象,show me the code.

users

id nickname avatar
1 慕容雪村 http://…/avatar.jpg
2 魔力鳥 http://…/avatar2.jpg
3 科比 http://…/avatar3.jpg

user_auths

id user_id identity_type identifier credential
1 1 email 123@example.com password_hash(密碼)
2 1 phone 13888888888 password_hash(密碼)
3 1 weibo 微博UID 微博access_token
4 2 username moliniao password_hash(密碼)
5 3 weixin 微信UserName 微信token

如果使用第三方登錄,則只要判斷 SELECT * FROM user_auths WHERE type=’weixin’ and identifier=’微信UserName’ ,如果有記錄,則直接登錄成功,使用新的token更新原token。假設與微信服務器通信不被劫持的情況下無需判斷憑證問題。

通過這個表結構設計,使許多原來糾結的問題瞬間解決,說說優點吧
一,站內登錄類型無限拓展,代碼改動小。如果真要支持身份證登錄了,只要少許幾處改動,無需修改表結構。
二,第三方登錄類型可用工廠模式批量拓展,新增第三方登錄類型的開發成本降到最低。
三,原來條件下,應用需要驗證手機號是否已驗證和郵箱是否已驗證,需要相對應多一個字段如 phone_verified 和 email_verified,如今只要在user_auths表中增加一個統一的verified字段,每種登錄方式都可以直觀看到是否已驗證情況。基于信任第三方登錄的數據準確性,默認第三方登錄都是已驗證。如果用戶修改登錄手機號或登錄郵箱,也能清晰跟蹤每一步的完成度。
四,可按需綁定任意數量的同類型登錄方式,即一個用戶可以綁定多個微信,可以有多個郵箱,可以有多個手機號,是不是很贊?當然你也可以限制一種登錄方式只有一條記錄。
五,在user_auths添加相應的時間和IP地址,就可以更加完整地跟蹤用戶的使用習慣,比如,已經不使用微博登錄兩年多,已經綁定微信300天
六,即使完全使用第三方帳號登錄,可在前端做到“無需注冊本站帳號”的效果。過去許多網站雖然支持第三方帳號登錄,但出于留存用戶等原因,第一次微博登錄回來,讓你再填寫一套他們網站的郵箱、密碼等信息,也就失去了微博登錄的最大意義。從技術上說,原有的結構導致除了在微博用戶表建立一個條目外,必須在用戶表建立一條對應的條目,而且一般情況下不能讓用戶表里的郵箱或者用戶名和密碼留空。用戶體驗好的,郵箱自動生成 微博ID@id.weibo.sina.com ,密碼則隨機生成。至于體驗不好的,只能說早知道還不如不用微博登錄呢!現在呢,我們的這個用戶表結構則完全沒有這樣的困擾,只要微博提供的昵稱和頭像地址就可以生成這個用戶,再關聯他的微博登錄記錄。而且我們的表結構意味著,用戶可以解除他的所有登錄方式,于是這個賬戶便徹底變成了沒法登錄的僵尸(解決辦法是在代碼里加一個限制,至少保留一條user_auths的記錄)。如果你非得得到用戶的郵箱,那么每次登錄的時候看到他不存在一條identify_type為email的記錄,則彈窗彈死他,讓他趕快填郵箱,否則啥都別干。
七,提升了邏輯思維能力。抽象出事物本質是碼農必備職業素養,通過對用戶表結構的學習研究,提高了鄙人的各方面技能,從此寫代碼一路順風順水…
八,如果你說郵箱和手機號就是用戶信息的組成部分,他們依然需要體現在users表中作為前端展示?沒問題,users表盡管拓展,users表里依然有email,phone,但他們僅僅作為“展示用途”,和昵稱、頭像、或者性別這些屬性沒有本質區別。在用戶信息表與用戶授權登錄拆分后,用戶信息表可以隨時增加任意字段,加星座,加生日,都沒問題,只需要在前端展示時多幾個輸入框,錄入時多幾行代碼,與用戶登錄相關的問題做到最大程度解耦。
有利必有弊,說說缺點。
一,原先的用戶判斷由1次SQL變成2次SQL請求。
二,用戶同時存在郵箱、用戶名、手機號等多種站內登錄方式時,改密碼時必須一起改,否則就變成了郵箱+新密碼,手機號+舊密碼訪問了,肯定是很詭異的情況。如果考慮到這一點,又要在user_auths表中新增一個表示站內登錄方式或第三方登錄方式的標識字段。
三,代碼量增加了,有些情況下邏輯判斷增加了,難度增大了。舉個例子,無論用戶是否已登錄,無論用戶是否已注冊過,都是點擊同一鏈接前往微博第三方授權后返回,可能出現幾種情況:
1,該微博在本站未注冊過,很好,直接給他注冊關聯并登錄;
2,該微博已經在本站存在,當前用戶未登錄,直接登錄成功;
3,該微博未在本站注冊,但當前用戶已經登錄并關聯的是另一個微博帳號,作何處理取決于是否允許綁定多個微博帳號;
4,該微博未在本站注冊過,當前用戶已登錄,嘗試進行綁定操作;
5,該微博已經注冊,用戶又已使用該帳號登錄,為何他重復綁定自己- -.
6,該微博已經在本站存在,但當前用戶已經登錄并關聯的是另一個微博帳號,作何處理?切換用戶或是報錯?(畫一個流程圖能更好描述這個問題)這個問題與采用的數據結構沒有關系,只是在做第三方帳號注冊登錄時遇到的各種情況,在此一并整理。

參考:
1.http://wpceo.com/user-database-table-design/
2.http://www.netkiller.cn/architect/database/user.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容