支持多种登录方式的数据库设计
一个带有用户系统的应用最基本登录方式是站内账号登录,但这种方式往往不能满足我们的需求。现在的应用基本都有站内账号、email、手机和一堆第三方登录,那么如果需要支持这么多种登录方式,或者还有银行卡登录、身份证登录等等更多的登录方式,我们的数据表应该怎么设计才更合理呢?
首先,一个用户不管有多少种登录方式,用户还是只有那一个用户,但登录方式却有多种。这就形成了一对多的关系:一个用户对应多个登录方式。
所以,我们就可以把用户表拆分成2张表,一张表存储用户基本的数据,另一张表存储登录授权相关的数据。我们可以向下面这样设计:
用户表【USERS】:
主键【ID】
用户名【USERNAME】
性别【GENDER】
年龄【AGE】
电话【PHONE】
状态【STATUS】
授权表【USER_AUTHS】:
主键【ID】
用户外键【USERID】:用户表对应的主键;
登录类型【IDENTITYTYPE】:登录类别,如:系统用户、邮箱、手机,或者第三方的QQ、微信、微博;
识别标识【IDENTIFIER】:身份唯一标识,如:登录账号、邮箱地址、手机号码、QQ号码、微信号、微博号;
授权凭证【CREDENTIAL】:站内账号是密码、第三方登录是Token;
是否验证【IFVERIFIED】:授权账号是否被验证;
这样我们创建一个用户,首先需要创建一条用户表的用户基础信息记录和一条或者多条授权表的授权记录。注意修改密码时也需要同时修改多条授权表记录,保证需要密码的登录方式凭证需要同步更新。
ID | USERNAME | GENDER | AGE | PHONE | STATUS |
1 | LUCY | FEMALE | 18 | 138----- | 有效 |
ID | USERID | IDENTITYTYPE | IDENTIFIER | CREDENTIAL | IFVERIFIED |
1 | 1 | 系统用户 | test | 888888 | YES |
2 | 1 | 邮箱 | *@QQ.COM | 888888 | YES |
3 | 1 | 手机 | 138--------- | 888888 | YES |
4 | 1 | 微信 | 138******** | token值 | YES |
5 | 1 | 微博 | weiboID | token值 | YES |
说说具体处理,用户发来邮箱/用户名/手机号和密码请求登录的时候,依然是先判断类型,以某用户使用了手机号登录为例,使用 SELECT * FROM USER_AUTHS WHERE IDENTITYTYPE='手机' AND IDENTIFIER='手机号' 查找条目。如有,则取出并判断密码是否和该条目的CREDENTIAL相符,相符则通过验证,随后通过USERID获取用户信息。
如果使用第三方登录,则只要判断 SELECT * FROM USER_AUTHS WHERE IDENTITYTYPE='微信' and IDENTIFIER='微信号'。如果有记录,则直接登录成功,使用新的token更新原token。假设与微信服务器通信不被劫持的情况下无需判断凭证问题。
通过这种表结构设计,使许多原来纠结的问题瞬间解决。
优点:
1、站内登录类型无限拓展,代码改动小。如果真要支持身份证登录了,只要少许几处改动,无需修改表结构。
2、第三方登录类型可用工场模式批量拓展,新增第三方登录类型的开发成本降到最低。
3、在USER_AUTHS表中增加一个统一的verified字段,每种登录方式都可以直观看到是否已验证情况。基于信任第三方登录的数据准确性,默认第三方登录都是已验证。如果用户修改登录手机号或登录邮箱,也能清晰跟踪每一步的完成度。
4、可按需绑定任意数量的同类型登录方式,即一个用户可以绑定多个微信,可以有多个邮箱,可以有多个手机号,是不是很赞!当然你也可以限制一种登录方式只有一条记录。
5、在USER_AUTHS添加相应的时间和IP地址,就可以更加完整地跟踪用户的使用习惯(此部分应该单独建立日志表)。比如,已经不使用微博登录两年多,已经绑定微信300天。
6、即使完全使用第三方帐号登录,可在前端做到“无需注册本站帐号”的效果。过去许多网站虽然支持第三方帐号登录,但出于留存用户等原因,第一次微博登录回来,让你再填写一套他们网站的邮箱、密码等信息,也就失去了微博登录的最大意义。
从技术上说,原有的结构导致除了在微博用户表建立一个条目外,必须在用户表建立一条对应的条目,而且一般情况下不能让用户表里的邮箱或者用户名和密码留空。用户体验好的,邮箱自动生成 微博ID@id.weibo.sina.com ,密码则随机生成。至于体验不好的,只能说早知道还不如不用微博登录呢!现在呢,我们的这个用户表结构则完全没有这样的困扰,只要微博提供的昵称和头像地址就可以生成这个用户,再关联他的微博登录记录。而且我们的表结构意味着,用户可以解除他的所有登录方式,于是这个账户便彻底变成了没法登录的僵尸(解决办法是在代码里加一个限制,至少保留一条USER_AUTHS的记录)。如果你非要得到用户的邮箱,那么每次登录的时候看到他不存在一条IDENTITYTYPE为email的记录,则弹窗弹死他,让他赶快填邮箱,否则啥都别干。
7、提升了逻辑思维能力。抽象出事物本质是码农必备职业素养。
8、如果你说邮箱和手机号就是用户信息的组成部分,他们依然需要体现在USERS表中作为前端展示。USERS表尽管拓展,USERS表里依然有email,phone。但它们仅仅作为“展示用途”,这和昵称、头像、或者性别这些属性没有本质区别。在用户信息表与用户授权登录拆分后,用户信息表可以随时增加任意字段,加星座,加生日,都没问题,只需要在前端展示时多几个输入框,录入时多几行代码,与用户登录相关的问题做到最大程度解耦。
缺点:
1、原先的用户判断由1次SQL变成2次SQL请求。
2、用户同时存在邮箱、用户名、手机号等多种站内登录方式时,改密码时必须一起改,否则就变成了邮箱+新密码,手机号+旧密码访问了,肯定是很诡异的情况。如果考虑到这一点,又要在USER_AUTHS表中新增一个表示站内登录方式或第三方登录方式的标识字段。
3、代码量增加了,有些情况下逻辑判断增加了,难度增大了。
举个例子,无论用户是否已登录,无论用户是否已注册过,都是点击同一链接前往微博第三方授权后返回,可能出现几种情况:
1)该微博在本站未注册过,很好,直接给他注册关联并登录;
2)该微博已经在本站存在,当前用户未登录,直接登录成功;
3)该微博未在本站注册,但当前用户已经登录并关联的是另一个微博帐号,作何处理取决于是否允许绑定多个微博帐号;
4)该微博未在本站注册过,当前用户已登录,尝试进行绑定操作;
posted on 2018-05-25 10:04 SuperSnowYao 阅读(10150) 评论(5) 编辑 收藏 举报