在Web系統中,用戶(hù)登錄是最基本的功能。要實(shí)現用戶(hù)名+密碼登錄,很多同學(xué)的第一想法就是直接創(chuàng )建一個(gè)Users表,包含username和password兩列,這樣,就可以實(shí)現登錄了:
id | username | password | name等其他字段----+----------+----------+---------------- A1 | bob | a1b23f2c | ... A2 | adam | c0932f32 | ...現在問(wèn)題來(lái)了,如果要讓用戶(hù)通過(guò)第三方登錄,比如微博登錄或QQ登錄,怎么集成進(jìn)來(lái)呢?
以微博登錄為例,由于微博使用OAuth2協(xié)議登錄,所以,一個(gè)登錄用戶(hù)會(huì )包含他的微博身份的ID,一個(gè)Access Token用于代表該用戶(hù)訪(fǎng)問(wèn)微博的API和一個(gè)過(guò)期時(shí)間。
要集成微博登錄,很多童鞋立刻想到把Users表擴展幾列,記錄下微博的信息:
id | username | password | weibo_id | weibo_access_token | weibo_expires | name等其他字段----+----------+----------+----------+--------------------+---------------+---------------- A1 | bob | a1b23f2c | W-012345 | xxxxxxxxxx | 604800 | ... A2 | adam | c0932f32 | W-234567 | xxxxxxxxxx | 604800 | ...加一個(gè)QQ登錄Users表就又需要加3列,如果這么擴展下去,改表都得累死,不要說(shuō)維護代碼了。
那怎么才能設計出靈活的登錄呢?
不妨換個(gè)角度考慮用戶(hù)登錄。當用戶(hù)以任意一種方式登錄成功后,我們讀取到的總是Users表對應的一行記錄,它實(shí)際上是用戶(hù)的個(gè)人資料(Profile),而登錄過(guò)程只是為了認證用戶(hù)(Authenticate),無(wú)論是本地用密碼驗證,還是委托第三方登錄,這個(gè)過(guò)程本質(zhì)上都是認證。
所以,如果把Profile和Authenticate分開(kāi),就十分容易理解了。Users表本身只存儲用戶(hù)的Profile:
id | name | birth等其他字段----+------+----------------- A1 | Bob | ... A2 | Adam | ...而通過(guò)用戶(hù)名口令登錄可視為一種Authenticate的方式,利用LocalAuth表維護:
id | user_id | username | password----+---------+----------+----------- 01 | A1 | bob | a1b23f2c 02 | A2 | adam | c0932f32通過(guò)微博登錄可視為另一種Authenticate方式,利用OAuth表維護:
id | user_id | weibo_id | weibo_access_token | weibo_expires----+---------+----------+--------------------+--------------- 11 | A1 | W-012345 | xxxxxxxxxx | 604800 12 | A2 | W-234567 | xxxxxxxxxx | 604800如果要添加另一種OAuth登錄,比如QQ登錄,增加一個(gè)表就可以了。不過(guò)既然大家都是OAuth家族的,不如統一到一個(gè)表,給每家起個(gè)名字區分就好了:
id | user_id | oauth_name | oauth_id | oauth_access_token | oauth_expires----+---------+------------+----------+--------------------+--------------- 11 | A1 | weibo | W-012345 | xxxxxxxxxx | 604800 12 | A2 | weibo | W-234567 | xxxxxxxxxx | 604800 13 | A1 | qq | Q-090807 | xxx-xxx-xxx | 86400 14 | A2 | qq | Q-807060 | xxx-xxx-xxx | 86400如果要增加一種新的登錄方式,比如SAML,那就再加一種類(lèi)型的表。
有些網(wǎng)站需要API訪(fǎng)問(wèn),API可以使用api_key和api_secret來(lái)認證,可是怎么把一個(gè)API訪(fǎng)問(wèn)關(guān)聯(lián)到一個(gè)用戶(hù)?方法還是增加一種API Auth的表:
id | user_id | api_key | api_secret----+---------+----------+------------ 11 | A1 | a-012345 | xxxxxxxxxx 12 | A2 | a-234567 | xxxxxxxxxx每一種X-Auth表都存儲了用戶(hù)的登錄認證信息,并通過(guò)user_id關(guān)聯(lián)到Users表。這樣一來(lái),不但登錄過(guò)程簡(jiǎn)化了,而且一個(gè)用戶(hù)可以使用多種方式登錄。只要登錄成功,拿到了user_id,最后讀取Users表是為了獲得用戶(hù)的Profile,這樣讀出來(lái)的數據也更安全,因為Users表不包含用戶(hù)口令,不會(huì )因為暴露API而不小心把口令給泄露出去。
聯(lián)系客服