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

先前设计

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,该微博已经在本站存在,但当前用户已经登录并关联的是另一个微博帐号,作何处理?切换用户或是报错?(画一个流程图能更好描述这个问题)这个问题与采用的数据结构没有关系,只是在做第三方帐号注册登录时遇到的各种情况,在此一并整理

拎壶带你冲----教育类mysql用户表设计参考的更多相关文章

  1. MySql数据表设计,索引优化,SQL优化,其他数据库

    MySql数据表设计,索引优化,SQL优化,其他数据库 1.数据表设计 1.1数据类型 1.2避免空值 1.3text类型优化 2.索引优化 2.1索引分类 2.2索引优化 3.SQL优化 3.1分批 ...

  2. Mysql—用户表详解(mysql.user)

    MySQL是一个多用户管理的数据库,可以为不同用户分配不同的权限,分为root用户和普通用户,root用户为超级管理员,拥有所有权限,而普通用户拥有指定的权限. MySQL是通过权限表来控制用户对数据 ...

  3. 数据库设计-Mysql数据库表设计的过程中几个关键点

    一.表设计过程中应该注意的数据类型 1)更小的通常更好 控制字节长度 2)使用合适的数据类型: 如tinyint只占8个位,char(1024)与varchar(1024)的对比,char用于类似定长 ...

  4. MySQL库表设计小技巧

    前言: 在我们项目开发中,数据库及表的设计可以说是非常重要,我遇到过很多库表设计比较杂乱的项目,像表名.字段名命名混乱.字段类型设计混乱等等,此类数据库后续极难维护与拓展.我一直相信只有优秀的库表设计 ...

  5. MySQL分类表设计--根据ID删除全部子类

    在做数据库分类表的时候,通常会有这样的设计:一个字段是ID,另一个字段PID,PID指向自己的上级分类: 这样的设计带来的问题是:我要删除一个类,我希望它的子类全部一起删除: 在不知道分类有多少层级的 ...

  6. Mysql学习总结(17)——MySQL数据库表设计优化

    1.选择优化的数据类型 MySQL支持很多种不同的数据类型,并且选择正确的数据类型对于获得高性能至关重要.不管选择何种类型,下面的简单原则都会有助于做出更好的选择: (1).更小通常更好 一般来说,要 ...

  7. mysql大表设计以及优化

    MYSQL千万级数据量的优化方法积累https://m.toutiao.com/group/6583260372269007374/?iid=6583260372269007374 MySQL 千万级 ...

  8. EF Code First MySql 主从表设计的一些需要注意的内容

    假如有下面两张表 public class Main { public int Id{get;set;} public string Name{get;set}; public virtual ICo ...

  9. Mysql实例 表设计

    目录 一.介绍 二.设计表格 三.查询 查都有哪些公司 查A公司都放了哪些广告 查A公司10月份该交多少广告费 四.分析 表结构设置 sql语句 其它功能 一.介绍 有一个公司叫月亮集团,他们旗下有很 ...

随机推荐

  1. 12.2 中的Data Guard Standby 密码文件自动同步 (Doc ID 2307365.1)

    Data Guard Standby Automatic Password file Synchronization in 12.2 (Doc ID 2307365.1) APPLIES TO: Or ...

  2. RTP Payload Format for H264 Video

    基础传输结构 rtp中对于h264数据的存储分为两层,分别是 VCL: video coding layer 视频编码层 这是h264中block, macro block 以及 slice级别的定义 ...

  3. CF 1114D(538,div2) Flood Fill

    https://codeforces.com/contest/1114/problem/D 题目 给一串数字,首先选择一个位置,类似于画图,然后每一轮按照以下步骤: 可以将这个位置所在的连通块改成其他 ...

  4. 剑指Offer-42.和为S的两个数字(C++/Java)

    题目: 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输出描述: 对应每个测试案例,输出两个数,小的先输出. 分析: ...

  5. 【SQL】多表查询中的 外连接 ,on,where

    先简单粗暴给个结论,多表连结查询中,on比where更早起作用,系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由where进行匹配过滤,where后语句为真,则能查询出来,而通过外连接 ...

  6. Git - Git本地仓库与GitHub远程仓库关联

    前言 Git本地仓库与GitHub仓库的关联逻辑如下 创建Key 在本地仓库下,新建Key文件夹,然后打开Key文件夹,单击鼠标右键,选择Git Bash Here. 输入命令:ssh-keygen ...

  7. Java SSM 商户管理系统 客户管理 库存管理 销售报表 项目源码

    需求分析: 有个厂家,下面有很多代理商(商户或门头等),之前商户进货.库存.销售.客户资料等记录在excel表格中 或者无记录,管理比较混乱,盈利情况不明.不能有效了解店铺经营情况和客户跟踪记录 厂家 ...

  8. HTML5播放视频,并使用ffmpeg对视频转编码

    网页加入视频可以用h5自带的video标签,这里用一个jQuery封装优化好的video视频组件videojs. videojs官方网站:https://docs.videojs.com/index. ...

  9. XMind 是一个全功能的思维导图和头脑风暴软件,为激发灵感和创意而生

    XMind 是一个全功能的思维导图和头脑风暴软件,为激发灵感和创意而生 https://www.xmind.cn/

  10. 树莓派设置frpc开机启动

    1.复制frpc启动命令及配置文件到系统相应目录: $ sudo cp frpc /usr/local/bin/frpc $ sudo mkdir /etc/frpc $ sudo cp frpc.i ...