用戶系統設計

用戶系統,主要分爲賬號體系和用戶信息兩大類。賬號體系包括,登陸驗證、註冊、第三方授權、以及權限管理。用戶信息包括,用戶地理位置、用戶屬性、用戶設備信息、還有用戶日誌信息。本文會介紹用戶系統的具體落地方案。

登陸驗證

在一般項目賬號體系中,一般會要求支持手機、郵箱、賬號、QQ、微信、微博實現登陸。後面三種方式都是基於第三方授權後,完成的身份驗證。手機、郵箱、賬號則是相對傳統的登錄方式。

用戶身份與登錄的授權方式是獨立開的,即用戶uid和登錄方式是一對多的關係。舉例來說,用戶A在使用微博授權登陸後,服務端鑑別身份信息爲uid=123。用戶A下次使用微信登陸,服務端鑑別身份同樣爲uid=123。不存在同一用戶A擁有多個賬號信息的現象。登陸授權表設計如下。

//用戶授權表
CREATE TABLE `user_auth` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `uid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '用戶id',
  `identity_type` tinyint(4) unsigned NOT NULL DEFAULT '1' COMMENT '1手機號 2郵箱 3用戶名 4qq 5微信 6騰訊微博 7新浪微博',
  `identifier` varchar(50) NOT NULL DEFAULT '' COMMENT '手機號 郵箱 用戶名或第三方應用的唯一標識',
  `certificate` varchar(20) NOT NULL DEFAULT '' COMMENT '密碼憑證(站內的保存密碼,站外的不保存或保存token)',
  `create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '綁定時間',
  `update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新綁定時間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `only` (`uid`,`identity_type`),
  KEY `idx_uid` (`uid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶授權表'

用戶信息

用戶信息,爲便於擴展,分成兩類。用戶基礎信息和用戶拓展信息。基本信息用來保存用戶的基本屬性,年齡、性別、生日、頭像、手機號碼等。擴展信息,用來保存用戶的設備信息或其他可擴展的內容。另外還有位置信息,這個可獨立出來,也可合併到擴展信息中,根據自己的使用場景來定。

//用戶基礎信息
CREATE TABLE `user_base` (
  `uid` bigint(20) NOT NULL COMMENT '用戶ID',
  `user_role` tinyint(2) unsigned NOT NULL DEFAULT '2' COMMENT '2正常用戶 3禁言用戶 4虛擬用戶 5運營',
  `register_source` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '註冊來源:1手機號 2郵箱 3用戶名 4qq 5微信 6騰訊微博 7新浪微博',
  `user_name` varchar(32) NOT NULL DEFAULT '' COMMENT '用戶賬號,必須唯一',
  `nick_name` varchar(32) NOT NULL DEFAULT '' COMMENT '用戶暱稱',
  `gender` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '用戶性別 0-female 1-male',
  `birthday` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '用戶生日',
  `signature` varchar(255) NOT NULL DEFAULT '' COMMENT '用戶個人簽名',
  `mobile` varchar(16) NOT NULL DEFAULT '' COMMENT '手機號碼(唯一)',
  `mobile_bind_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '手機號碼綁定時間',
  `email` varchar(100) NOT NULL DEFAULT '' COMMENT '郵箱(唯一)',
  `email_bind_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '郵箱綁定時間',
  `face` varchar(255) NOT NULL DEFAULT '' COMMENT '頭像',
  `face200` varchar(255) NOT NULL DEFAULT '' COMMENT '頭像 200x200x80',
  `srcface` varchar(255) NOT NULL DEFAULT '' COMMENT '原圖頭像',
  `create_time` int(11) unsigned NOT NULL COMMENT '創建時間',
  `update_time` int(11) unsigned NOT NULL COMMENT '修改時間',
  `push_token` varchar(50) NOT NULL COMMENT '用戶設備push_token',
  PRIMARY KEY (`uid`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶基礎信息表'

//用戶擴展信息
CREATE TABLE `user_extra` (
  `uid` bigint(20) NOT NULL COMMENT '用戶 ID',
  `vendor` varchar(64) NOT NULL DEFAULT '' COMMENT '手機廠商:apple|htc|samsung,很少用',
  `client_name` varchar(50) NOT NULL DEFAULT '' COMMENT '客戶端名稱,如hjskang',
  `client_version` varchar(50) NOT NULL DEFAULT '' COMMENT '客戶端版本號,如7.0.1',
  `os_name` varchar(16) NOT NULL DEFAULT '' COMMENT '設備號:android|ios',
  `os_version` varchar(16) NOT NULL DEFAULT '' COMMENT '系統版本號:2.2|2.3|4.0|5.1',
  `device_name` varchar(32) NOT NULL DEFAULT '' COMMENT '設備型號,如:iphone6s、u880、u8800',
  `device_id` varchar(128) NOT NULL DEFAULT '' COMMENT '設備ID',
  `idfa` varchar(50) NOT NULL DEFAULT '' COMMENT '蘋果設備的IDFA',
  `idfv` varchar(50) NOT NULL DEFAULT '' COMMENT '蘋果設備的IDFV',
  `market` varchar(20) NOT NULL DEFAULT '' COMMENT '來源',
  `create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '添加時間',
  `update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新時間',
  `extend1` varchar(100) NOT NULL DEFAULT '' COMMENT '擴展字段1',
  `extend2` varchar(100) NOT NULL DEFAULT '' COMMENT '擴展字段2',
  `extend3` varchar(100) NOT NULL DEFAULT '' COMMENT '擴展字段3',
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶額外信息表'

//用戶位置信息
CREATE TABLE `user_location` (
  `uid` bigint(20) unsigned NOT NULL COMMENT '用戶ID',
  `curr_nation` varchar(10) NOT NULL DEFAULT '' COMMENT '所在地國',
  `curr_province` varchar(10) NOT NULL DEFAULT '' COMMENT '所在地省',
  `curr_city` varchar(10) NOT NULL DEFAULT '' COMMENT '所在地市',
  `curr_district` varchar(20) NOT NULL DEFAULT '' COMMENT '所在地地區',
  `location` varchar(255) NOT NULL DEFAULT '' COMMENT '具體地址',
  `longitude` decimal(10,6) DEFAULT NULL COMMENT '經度',
  `latitude` decimal(10,6) DEFAULT NULL COMMENT '緯度',
  `update_time` int(11) unsigned DEFAULT '0' COMMENT '修改時間',
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶定位表'

用戶日誌信息

日誌信息,用來保存用戶註冊或者登陸行爲的。另外會有一些修改密碼或者修改重要信息的日誌記錄。

//用戶登陸日誌
CREATE TABLE `user_login_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `uid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '用戶uid',
  `type` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '登錄方式 第三方/郵箱/手機等',
  `command` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '操作類型 1登陸成功  2登出成功 3登錄失敗 4登出失敗',
  `version` varchar(32) NOT NULL DEFAULT '1.0' COMMENT '客戶端版本號',
  `client` varchar(20) NOT NULL DEFAULT 'dabaozha' COMMENT '客戶端',
  `device_id` varchar(64) NOT NULL DEFAULT '' COMMENT '登錄時設備號',
  `lastip` varchar(32) NOT NULL DEFAULT '' COMMENT '登錄ip',
  `os` varchar(16) NOT NULL DEFAULT '' COMMENT '手機系統',
  `osver` varchar(32) NOT NULL DEFAULT '' COMMENT '系統版本',
  `text` varchar(200) NOT NULL DEFAULT '',
  `create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '操作時間',
  PRIMARY KEY (`id`),
  KEY `idx_uid_type_time` (`uid`,`type`,`create_time`) USING BTREE,
  KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='登陸日誌表'

//用戶註冊日誌
CREATE TABLE `user_register_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `uid` bigint(20) unsigned NOT NULL COMMENT '用戶ID',
  `register_method` tinyint(2) unsigned NOT NULL COMMENT '註冊方式1手機號 2郵箱 3用戶名 4qq 5微信 6騰訊微博 7新浪微博',
  `register_time` int(11) NOT NULL COMMENT '註冊時間',
  `register_ip` varchar(16) NOT NULL DEFAULT '' COMMENT '註冊IP',
  `register_client` varchar(16) NOT NULL DEFAULT '' COMMENT '註冊客戶端',
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='用戶註冊日誌表'

//修改信息日誌
CREATE TABLE `user_info_update` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `uid` bigint(20) unsigned NOT NULL COMMENT '用戶ID',
  `attribute_name` varchar(30) NOT NULL COMMENT '屬性名',
  `attribute_old_val` varchar(30) NOT NULL DEFAULT '' COMMENT '屬性對應舊的值',
  `attribute_new_val` varchar(30) NOT NULL DEFAULT '' COMMENT '屬性對應新的值',
  `update_time` int(11) NOT NULL COMMENT '修改時間',
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='用戶註冊日誌表'

全局uid

建議不要使用表的主鍵作爲用戶ID,而是使用ID生成器(發號器)生成用戶的唯一標示guid。當用戶量急劇上升時,往往會採取分庫分表的方法,然後通過將uid取餘寫到不同的表中。如果單純的以某個表主鍵作爲ID。會限制插入性能和增加業務複雜度,其次在分佈式數據庫中也無法保證ID唯一性。

全局ID生成,是有很多方案的。簡單一點,可以採用redis自增屬性,因爲其具有原子性,在分佈式壞境中,能保證ID的唯一性。另外還有其他的一些開源方案,可自行Google。

Access Token

與傳統的Session相比,Access Token比較適合做RESTful Api開發。傳統Web應用中,用戶登陸後會寫用戶信息到cookie中,服務端通過Session就能得到用戶的身份。

Access Token的是OAuth2.0中用戶經過授權後,返回調用API的憑證。對於自己的應用來講,用戶在登錄後,即返回access_token。在token有效期內可憑藉此憑證,調用其他接口。對於access_token的刷新有兩種方案,第一種每次用戶重啓app時,重新refresh。第二種,在調用週期內服務端發現access token可能過期時,返回新的token給客戶端。

至於Access Token的生成,這個並沒有規定,只要保證其唯一性即可。簡單點,對用戶uid和當前時間哈希得到新的Access Token,並設置過期時間。另外也可以採用JWT實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章