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

先前设计

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)
这个系统最大的特色就是,用户信息表不保存任何密码,不保存任何登录信息(如用户名、手机号、邮箱),只留有昵称、头像等基础信息。所有和授权相关(且基本前端展示无关的),都放在用户信息授权表,用户信息表和用户授权表是一对多的关系。说起来太抽象,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=’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,该微博已经在本站存在,但当前用户已经登录并关联的是另一个微博帐号,作何处理?切换用户或是报错?(画一个流程图能更好描述这个问题)这个问题与采用的数据结构没有关系,只是在做第三方帐号注册登录时遇到的各种情况,在此一并整理。

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

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

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

  2. 第三方登录用户信息表设计

    user表:站内账号表,即原始的账号-密码信息表 字段有 user_id ,username,password social_account表:第三方账号信息表 如 wx_account :微信账号信 ...

  3. 会员权限 表设计mysql_求用户-权限数据库表设计方案

    前不久做的一个系统,用户-权限是这样设计的, 用户表: Id int primary key not null identity(1,1) 主键 UloginName varchar(20) not ...

  4. web表单设计:点石成金_设计复杂的用户表单:12个UX最佳实践

    web表单设计:点石成金 It's been a few years that I've been taking interest in designing complex user forms, w ...

  5. python实验三:P2P网络带宽数据主表Training_Master、用户信息更新表Training_Userupdate和登录信息表Training_LogInfo

    目录 一.问题描述 1.读取并查查看P2P网络带宽数据主表Training_Master的基本信息 2.提取用户信息更新表Training_Userupdate和登录信息表Training_LogIn ...

  6. 数据库表设计2:用户关注粉丝

    前言:在社交类系统中,用户与用户的好友关系的设计必不可少,那么如何设计好友的数据库至关重要,本篇文章带大家学习一下微博关注粉丝数据表相关的设计方案. 1.用户好友关系分类 第一步,有一张用户表,表内包 ...

  7. 数据库表设计1:用户权限管理

    前言:权限管理是所有后台系统的都会涉及的一个重要组成部分,主要目的是对不同用户访问资源进行权限的控制,避免因权限控制缺失或操作不当引发的风险问题,如操作错误,隐私数据泄露等问题. 1.RBAC简介 R ...

  8. python与vfp做桌面数据库_VFP设计窗口登录

    呵呵.我有两种电常用的方法,我给你贴一种我最常用的出来哈(我以前两天做的一个超市进销存管理系统为列): 1.在"超市数据库"数据库中建立数据表"用户表",设置如 ...

  9. oracle 分表设计,oracle 分库分表(sharding)

    数据库Sharding的基本思想和切分策 关于垂直切分Vertical Sharding的粒度 数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示 数据库分库分表(sharding) ...

最新文章

  1. 人工智能开始应用于美国金融业 但在中国遭遇滑铁卢
  2. 每日一皮:你有没有过 Bug 变 Feature 的高光时刻?
  3. 【CSS3 DEMO】扑克正反面翻牌效果
  4. 模板:树上启发式合并(dsu on tree)
  5. 两个精彩的比喻:吞吐量和延迟、信号量和互斥锁
  6. 时隔 15 年,苹果的自研 ARM 芯片为何能取代 Intel 处理器?
  7. pdfpcell输出换行_poi导出Excel(cell单元格里的一串文字,换行显示,设置字体)...
  8. python快速入门神器 知乎_Python爬虫偷懒神器!快速一键生成Python爬虫请求头
  9. 人工智能知识全面讲解: RBF神经网络
  10. 图——基本的图算法(四)关键路径
  11. ambari集群修改ip地址
  12. linux 内存 参数,linux free命令参数及用法详解(linux查看内存命令)
  13. angular报$injector / unpr的错误
  14. 【学习笔记】PHP进阶
  15. oracle税务运维脚本练习,荣欣Linux运维+Oracle DBA初级+高级全套实战训练
  16. 你也能看懂的:主成分分析法
  17. qq2013 beta4(6734)木头显ip v10.4.2
  18. Shader学习23——描边+辉光
  19. mybatis注解记录
  20. 使用Windows自带chkdsk命令修复一些硬盘和U盘存储不了数据的问题

热门文章

  1. ​2 万字系统总结,带你实现 Linux 命令自由?
  2. 手机号码归属地api文档
  3. linux hase数据,Linux取得Redis数据库中hash类型的所有feild或者所有value
  4. 【Python笔记】列表基础操作 :创建,增加、删除、查询。附加:练习题。用简单代码解释。
  5. 企业文件加密软件如何做到根源防止泄密?全面专业的数据防泄密方案怎么选
  6. 运行 dist 打包文件:简单得很!!!
  7. w ndows10装什么浏览器,Windows10系统默认启用IE浏览器方法
  8. 修改el-input叉号的样式
  9. 磁共振t1t2信号记忆顺口溜_【 磁共振t1与t2是啥意义】_特点_特征-大众养生网
  10. 笔记本电脑外接显示器完全攻略(图文说明)