淺談數據庫用戶表結構設計

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

先前設計

id
username
password

用戶名加上密碼,解決簡單需求瘾敢,留個id作為其他表的外鍵辫封。當然,那時候密碼還可能是明文存儲廉丽,好點的知道m(xù)d5倦微。

后來呢,隨著業(yè)務需求的拓展正压,要加個用戶狀態(tài) status 判斷用戶是否被封禁欣福,注冊時間和注冊IP地址、上次登錄時間和IP地址備查(并衍生出登錄記錄表焦履,用來判斷是否異地登錄等拓劝,在此不表),用戶角色/權限 role (又衍生出用戶角色權限關系嘉裤,還是另文討論)郑临,業(yè)務也需要個人的個人信息如真實姓名、地址等也一股腦往上添加屑宠,現在形成了一個很完整的用戶關系表厢洞。

id
username
password
realname
address

status
role
register_time
register_ip
login_time
login_ip

現在問題來了,進入Web2.0時代典奉,微博開放了第三方網站登錄躺翻,用微博帳號就能登錄我們的網站,老板說卫玖,這個我們得要公你。加個微博用戶登錄表吧,當然假瞬,得和我們自己的用戶表關聯(lián)陕靠,這個微博用戶信息表如下:

id 自增ID
user_id 關聯(lián)本站用戶ID
uid 微博唯一ID
access_token
access_expire

這還不算完,QQ又開放用戶登錄了脱茉,一下子要接入好多家第三方登錄了剪芥,只能就著“微博用戶信息表”繼續(xù)加類型加判斷,如果是每個第三方登錄都新建一個表芦劣,肯定會瘋的粗俱。

時代變了,進入了移動互聯(lián)網時代虚吟,怎么也得支持個手機號登錄吧寸认?所以現在每家標配都是:用戶名/郵箱/手機號登錄,外加一系列微博串慰、微信等第三方登錄偏塞。表結構如下:

用戶表
id
username
email
phone

用戶第三方登錄表
id
user_id
app_type
app_user_id
access_token

用戶在輸入框輸入用戶名/郵箱/手機號和密碼之后,后臺判斷是郵箱邦鲫、手機號或是用戶名灸叼,再根據條件查詢是否為特定用戶。

這個表結構能夠承載未來一段時間的業(yè)務需求了庆捺。如果說某天冒出了一個新的登錄方式古今,比如身份證號登錄,怎么辦滔以?繼續(xù)在用戶表加字段捉腥?我覺得有更好的選擇。

改進版

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

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

這個系統(tǒng)最大的特色就是颅崩,用戶信息表不保存任何密碼,不保存任何登錄信息(如用戶名蕊苗、手機號沿后、郵箱),只留有昵稱朽砰、頭像等基礎信息尖滚。所有和授權相關(且基本前端展示無關的),都放在用戶信息授權表瞧柔,用戶信息表和用戶授權表是一對多的關系漆弄。說起來太抽象,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|

說說具體處理造锅,用戶發(fā)來郵箱/用戶名/手機號和密碼請求登錄的時候撼唾,依然是先判斷類型,以某用戶使用了手機號登錄為例哥蔚,使用 SELECT * FROM user_auths WHERE type=’phone’ and identifier=’手機號’ 查找條目倒谷,如有蛛蒙,取出并判斷password_hash(密碼)是否和該條目的credential相符,相符則通過驗證渤愁,隨后通過user_id獲取用戶信息牵祟。

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

通過這個表結構設計,使許多原來糾結的問題瞬間解決滓玖,說說優(yōu)點吧

一坪哄,站內登錄類型無限拓展,代碼改動小呢撞。如果真要支持身份證登錄了损姜,只要少許幾處改動,無需修改表結構殊霞。

二摧阅,第三方登錄類型可用工場模式批量拓展,新增第三方登錄類型的開發(fā)成本降到最低绷蹲。

三棒卷,原來條件下,應用需要驗證手機號是否已驗證和郵箱是否已驗證祝钢,需要相對應多一個字段如 phone_verified 和 email_verified比规,如今只要在user_auths表中增加一個統(tǒng)一的verified字段,每種登錄方式都可以直觀看到是否已驗證情況拦英⊙咽玻基于信任第三方登錄的數據準確性,默認第三方登錄都是已驗證疤估。如果用戶修改登錄手機號或登錄郵箱灾常,也能清晰跟蹤每一步的完成度。

四铃拇,可按需綁定任意數量的同類型登錄方式钞瀑,即一個用戶可以綁定多個微信,可以有多個郵箱慷荔,可以有多個手機號雕什,是不是很贊?當然你也可以限制一種登錄方式只有一條記錄。

五贷岸,在user_auths添加相應的時間和IP地址壹士,就可以更加完整地跟蹤用戶的使用習慣,比如凰盔,已經不使用微博登錄兩年多墓卦,已經綁定微信300天

六倦春,即使完全使用第三方帳號登錄户敬,可在前端做到“無需注冊本站帳號”的效果。過去許多網站雖然支持第三方帳號登錄睁本,但出于留存用戶等原因尿庐,第一次微博登錄回來,讓你再填寫一套他們網站的郵箱呢堰、密碼等信息抄瑟,也就失去了微博登錄的最大意義。從技術上說枉疼,原有的結構導致除了在微博用戶表建立一個條目外皮假,必須在用戶表建立一條對應的條目,而且一般情況下不能讓用戶表里的郵箱或者用戶名和密碼留空骂维。用戶體驗好的惹资,郵箱自動生成 微博ID@id.weibo.sina.com ,密碼則隨機生成航闺。至于體驗不好的褪测,只能說早知道還不如不用微博登錄呢!現在呢潦刃,我們的這個用戶表結構則完全沒有這樣的困擾侮措,只要微博提供的昵稱和頭像地址就可以生成這個用戶,再關聯(lián)他的微博登錄記錄乖杠。而且我們的表結構意味著分扎,用戶可以解除他的所有登錄方式,于是這個賬戶變徹底變成了沒法登錄的僵尸(解決辦法是在代碼里加一個限制胧洒,至少保留一條user_auths的記錄)畏吓。如果你非得得到用戶的郵箱,那么每次登錄的時候看到他不存在一條identify_type為email的記錄略荡,則彈窗彈死他庵佣,讓他趕快填郵箱,否則啥都別干汛兜。

七巴粪,提升了邏輯思維能力。抽象出事物本質是碼農必備職業(yè)素養(yǎng),通過對用戶表結構的學習研究肛根,提高了鄙人的各方面技能辫塌,從此寫代碼一路順風順水…

八,如果你說郵箱和手機號就是用戶信息的組成部分派哲,他們依然需要體現在users表中作為前端展示臼氨?沒問題,users表盡管拓展芭届,users表里依然有email,phone储矩,但他們僅僅作為“展示用途”,和昵稱褂乍、頭像持隧、或者性別這些屬性沒有本質區(qū)別。在用戶信息表與用戶授權登錄拆分后逃片,用戶信息表可以隨時增加任意字段屡拨,加星座,加生日褥实,都沒問題呀狼,只需要在前端展示時多幾個輸入框,錄入時多幾行代碼损离,與用戶登錄相關的問題做到最大程度解耦哥艇。

有利必有弊,說說缺點草冈。

一她奥,原先的用戶判斷由1次SQL變成2次SQL請求。

二怎棱,用戶同時存在郵箱哩俭、用戶名、手機號等多種站內登錄方式時拳恋,改密碼時必須一起改凡资,否則就變成了郵箱+新密碼,手機號+舊密碼訪問了谬运,肯定是很詭異的情況隙赁。如果考慮到這一點,又要在user_auths表中新增一個表示站內登錄方式或第三方登錄方式的標識字段梆暖。

三伞访,代碼量增加了,有些情況下邏輯判斷增加了轰驳,難度增大了厚掷。舉個例子弟灼,無論用戶是否已登錄,無論用戶是否已注冊過冒黑,都是點擊同一鏈接前往微博第三方授權后返回田绑,可能出現幾種情況:
1,該微博在本站未注冊過抡爹,很好掩驱,直接給他注冊關聯(lián)并登錄;
2冬竟,該微博已經在本站存在欧穴,當前用戶未登錄,直接登錄成功诱咏;
3苔可,該微博未在本站注冊泊愧,但當前用戶已經登錄并關聯(lián)的是另一個微博帳號闺阱,作何處理取決于是否允許綁定多個微博帳號吓笙;
4,該微博未在本站注冊過苟鸯,當前用戶已登錄,嘗試進行綁定操作棚点;
5早处,該微博已經注冊,用戶又已使用該帳號登錄瘫析,為何他重復綁定自己.
6砌梆,該微博已經在本站存在,但當前用戶已經登錄并關聯(lián)的是另一個微博帳號贬循,作何處理咸包?切換用戶或是報錯?(畫一個流程圖能更好描述這個問題)這個問題與采用的數據結構沒有關系杖虾,只是在做第三方帳號注冊登錄時遇到的各種情況烂瘫,在此一并整理。

轉自:http://wpceo.com/user-database-table-design/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末奇适,一起剝皮案震驚了整個濱河市坟比,隨后出現的幾起案子,更是在濱河造成了極大的恐慌嚷往,老刑警劉巖葛账,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異皮仁,居然都是意外死亡籍琳,警方通過查閱死者的電腦和手機茄茁,發(fā)現死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來巩割,“玉大人裙顽,你說我怎么就攤上這事⌒福” “怎么了愈犹?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長闻丑。 經常有香客問我漩怎,道長,這世上最難降的妖魔是什么嗦嗡? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任勋锤,我火速辦了婚禮,結果婚禮上侥祭,老公的妹妹穿的比我還像新娘叁执。我一直安慰自己,他們只是感情好矮冬,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布谈宛。 她就那樣靜靜地躺著,像睡著了一般胎署。 火紅的嫁衣襯著肌膚如雪吆录。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天琼牧,我揣著相機與錄音恢筝,去河邊找鬼。 笑死巨坊,一個胖子當著我的面吹牛撬槽,可吹牛的內容都是我干的。 我是一名探鬼主播抱究,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼恢氯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鼓寺?” 一聲冷哼從身側響起勋拟,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎妈候,沒想到半個月后敢靡,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡苦银,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年啸胧,在試婚紗的時候發(fā)現自己被綠了赶站。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡纺念,死狀恐怖贝椿,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情陷谱,我是刑警寧澤烙博,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站烟逊,受9級特大地震影響渣窜,放射性物質發(fā)生泄漏。R本人自食惡果不足惜宪躯,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一乔宿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧访雪,春花似錦详瑞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至肝陪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刑顺,已是汗流浹背氯窍。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蹲堂,地道東北人狼讨。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像柒竞,于是被迫代替她去往敵國和親政供。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354