说起用户表 , 大概是每个应用/网站立项动工考虑的第一件事情 ; 用户表结构的设计 , 算是整个后台架构的基石 ; 如果基石不稳 , 待到后面需求跟进了发现不能应付 , 回过头来反复修改用户表 , 要大大小小作改动的地方也不少 ; 与其如此 , 不妨设计用户表之初就考虑可拓展性 , 争取不需要太多额外代价的情况下一步到位 ;

先前设计

id
username
password

用户名加上密码 , 解决简单需求 , 留个 ID 作为其他表的外键 ; 当然 , 那时候密码还可能是明文存储 , 好点的知道 MD5 ;

后来呢 , 随着业务需求的拓展 , 要加个用户状态 status 判断用户是否被封禁 , 注册时间和注册 IP 地址 , 上次登录时间和 IP 地址备查 (并衍生出登录记录表 , 用来判断是否异地登录等 , 在此不表) , 用户角色/权限 role (又衍生出用户角色权限关系 , 还是另文讨论) , 业务也需要个人的个人信息如真实姓名 , 地址等也一股脑往上添加 , 现在形成了一个很完整的用户关系表 ;

id
username
password
realname
address
…
status
role
register_time
register_ip
login_time
login_ip

现在问题来了 , 进入 Web2.0 时代 , 微博开放了第三方网站登录 , 用微博帐号就能登录我们的网站 , 老板说 , 这个我们得要 , 加个微博用户登录表吧 , 当然 , 得和我们自己的用户表关联 , 这个微博用户信息表如下 :

id    自增 ID
user_id    关联本站用户 ID
uid    微博唯一 ID
access_token
access_expire

这还不算完 , QQ又开放用户登录了 , 一下子要接入好多家第三方登录了 , 只能就着 “微博用户信息表” 继续加类型加判断 , 如果是每个第三方登录都新建一个表 , 肯定会疯的 ;
时代变了 , 进入了移动互联网时代 , 怎么也得支持个手机号登录吧 , 所以现在每家标配都是 : 用户名/邮箱/手机号 登录 , 外加一系列微博 , 微信等第三方登录 , 表结构如下 :

用户表

id
username
email
phone
…

用户第三方登录表

id
user_id
app_type
app_user_id
access_token
…

用户在输入框输入 用户名/邮箱/手机号和密码 之后 , 后台判断是邮箱 , 手机号或是用户名 , 再根据条件查询是否为特定用户 ;
这个表结构能够承载未来一段时间的业务需求了 , 如果说某天冒出了一个新的登录方式 , 比如身份证号登录 , 怎么办 ? 继续在用户表加字段 ? 我觉得有更好的选择 ;

改进版

无论 username + password , 还是 phone + password , 都是一种 用户信息+密码 的验证形式;再来理解第三方登录 , 其实它也是用户信息+密码的形式 , 用户信息即第三方系统中的 ID (第三方登录一定会给一个在他们系统中的唯一标识) , 密码即 access_token , 只不过是一种有使用时效定期修改的密码 ; 所以我们把它抽象出了用户基础信息表加上用户授权信息表的形式 ;

用户基础信息表 users

id
nickname
avatar

用户授权信息表 user_auths

id
user_id
identity_type    登录类型 (手机号/邮箱/用户名) 或第三方应用名称 (微信 , 微博等)
identifier    标识 (手机号/邮箱/用户名或第三方应用的唯一标识)
credential    密码凭证 (站内的保存密码 , 站外的不保存或保存 token)

这个系统最大的特色就是 , 用户信息表不保存任何密码 , 不保存任何登录信息 (如用户名 , 手机号 , 邮箱) , 只留有昵称 , 头像等基础信息 ; 所有和授权相关 (且基本前端展示无关的) , 都放在用户信息授权表 , 用户信息表和用户授权表是一对多的关系 ; 说起来太抽象 , 表现如下 :

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= 'phone' and identifier= '手机号' 查找条目 , 如有 , 取出并判断 password_hash (密码)是否和该条目的 credential 相符 , 相符则通过验证 , 随后通过 user_id 获取用户信息 ;
如果使用第三方登录 , 则只要判断 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 , 该微博已经在本站存在 , 但当前用户已经登录并关联的是另一个微博帐号 , 作何处理 ? 切换用户或是报错 ? (画一个流程图能更好描述这个问题) 这个问题与采用的数据结构没有关系 , 只是在做第三方帐号注册登录时遇到的各种情况 , 在此一并整理 ;

作者 Github : tojohnonly , 博客 : EnskDeCode

浅谈数据库用户表结构设计和第三方登录相关推荐

  1. 用户数据表设计借鉴 浅谈数据库用户表结构设计,第三方登录 基于 Token 的身份验证

    最近对用户数据表的设计比较感兴趣,看到了两篇比较好的文章. 浅谈数据库用户表结构设计,第三方登录 转载于: https://www.cnblogs.com/jiqing9006/p/5937733.h ...

  2. 第三方登录mysql表_浅谈数据库用户表结构设计,第三方登录

    说起用户表,大概是每个应用/网站立项动工(码农们)考虑的第一件事情.用户表结构的设计,算是整个后台架构的基石.如果基石不稳,待到后面需求跟进了发现不能应付,回过头来反复修改用户表,要大大小小作改动的地 ...

  3. 浅谈数据库用户表结构设计,第三方登录

    说起用户表,大概是每个应用/网站立项动工(码农们)考虑的第一件事情.用户表结构的设计,算是整个后台架构的基石.如果基石不稳,待到后面需求跟进了发现不能应付,回过头来反复修改用户表,要大大小小作改动的地 ...

  4. mysql用户登录和第三方登录_mysql 用户表结构设计,第三方登录

    说起用户表,大概是每个应用/网站立项动工(码农们)考虑的第一件事情.用户表结构的设计,算是整个后台架构的基石.如果基石不稳,待到后面需求跟进了发现不能应付,回过头来反复修改用户表,要大大小小作改动的地 ...

  5. 第三方登录数据库用户表结构设计

    说起用户表,大概是每个应用/网站立项动工(码农们)考虑的第一件事情.用户表结构的设计,算是整个后台架构的基石.如果基石不稳,待到后面需求跟进了发现不能应付,回过头来反复修改用户表,要大大小小作改动的地 ...

  6. 数据库用户表结构设计-多种注册方式含第三方登录

    传统互联网已经过渡到移动互联网的时代,我们在开发android.ios.小程序等的时候,客户端的注册方式已经非常的丰富多样.所以,后台的用户表的设计也需要适应不同注册方式「不断扩张」及「相互绑定」的情 ...

  7. mysql系统研究现状_浅谈数据库的现状和发展 毕业论文.doc

    浅谈数据库的现状和发展 摘 要 学生学籍管理系统是一个教育单位不可缺少的部分,它的对于学校管理至关重要学生学籍管理系统能够为用户提供信息和快捷的查询手段.使用传统人工方式管理文件学籍,这种管理方式存在 ...

  8. 浅谈数据库设计技巧(上)

    浅谈数据库设计技巧(上) 说到数据库,我认为不能不先谈数据结构.1996年,在我初入大学学习计算机编程时,当时的老师就告诉我们说:计算机程序=数据结构+算法.尽管现在的程序开发已由面向过程为主逐步过渡 ...

  9. 浅谈数据库优化方面的经验

    浅谈数据库优化方面的经验 任何系统.网站几乎都离不开数据库,数据库好比人大脑的记忆系统,没有了数据库就没有了记忆系统.而数据库优化则相当于在同等智力的情况下,利用一种高效率地记忆方法进行更快更优的记忆 ...

  10. 并发执行变成串行_大神浅谈数据库并发控制 锁和 MVCC

    在学习几年编程之后,你会发现所有的问题都没有简单.快捷的解决方案,很多问题都需要权衡和妥协,而本文介绍的就是数据库在并发性能和可串行化之间做的权衡和妥协 - 并发控制机制.  如果数据库中的所有事务 ...

最新文章

  1. Fertility of Soils:根系C/P计量比影响水稻残根周际酶活的时空动态分布特征
  2. checkbox居中 editor_C1FlexGrid绑定自定义Editor-C1CheckBox
  3. 【软件设计师】2020-08-06
  4. css 跳动的心_如何用纯CSS为您的情人打造一颗跳动的心
  5. 在DrawingVisual上绘制圆形的进度条,类似于IOS系统风格。
  6. codeforces 617A-C语言解题报告
  7. eclipse中不能找到dubbo.xsd报错”cvc-complex-type.2.4.c“的 两种解决方法
  8. MTK 驱动(69)---MTK平台 电池驱动相关
  9. nginx1.8.1反向代理、负载均衡功能的实现
  10. mybatis oracle生成注释,MyBatis Generator生成Oracle数据库对应实体类时无法获取注释问题...
  11. [转]关于Microsoft.Office.Interop组件接口的调用方法
  12. 图书期刊信息管理系统c语言,基于C语言的图书馆管理系统.doc
  13. 数据挖掘 任务一:预测贷款是否逾期
  14. 多个无线WIFI路由器之间实现不掉线无缝切换的设置方法
  15. 多目标线性规划(matlab编程)
  16. 盲盒小程序的开发功能介绍,优势有哪些
  17. 谷歌地图开发:地理编码和反地理编码
  18. 密码学系列(一):密码行业、政策介绍
  19. 大数据趣味学习探讨(二):我是怎么坚持学习的
  20. angular单个页面加载多个ng-app

热门文章

  1. 这可能是史上最全的常用学术网站
  2. 缠论中第49课:没必要参与操作级别及以上级别的下跌与超过操作级别的盘整,如何理解与应用?
  3. CF1427F-Boring Card Game【贪心】
  4. Android MediaRecorder录制视频
  5. 爬虫:Instagram信息爬取
  6. 【vue】微信sdk中接口和标签本地调试
  7. 联想计算机管理员权限设置,联想电脑windows10管理员权限开启的4种方法
  8. alpha版、beta版、rc版的意思
  9. UML实例(五):在线购物系统设计类图
  10. 讓TQ2440也用上設備樹(1)