设计一个可扩展的用户登录系统
在Web系统中,用户登录是最基本的功能。要实现用户名+密码登录,很多同学的第一想法就是直接创建一个Users
表,包含username
和password
两列,这样,就可以实现登录了:
id | username | password | name等其他字段----+----------+----------+----------------
A1 | bob | a1b23f2c | ...
A2 | adam | c0932f32 | ...
现在问题来了,如果要让用户通过第三方登录,比如微博登录或QQ登录,怎么集成进来呢?
以微博登录为例,由于微博使用OAuth2协议登录,所以,一个登录用户会包含他的微博身份的ID,一个Access Token用于代表该用户访问微博的API和一个过期时间。
要集成微博登录,很多童鞋立刻想到把Users
表扩展几列,记录下微博的信息:
id | username | password | weibo_id | weibo_access_token | weibo_expires | name等其他字段----+----------+----------+----------+--------------------+---------------+----------------
A1 | bob | a1b23f2c | W-012345 | xxxxxxxxxx | 604800 | ...
A2 | adam | c0932f32 | W-234567 | xxxxxxxxxx | 604800 | ...
加一个QQ登录Users
表就又需要加3列,如果这么扩展下去,改表都得累死,不要说维护代码了。
那怎么才能设计出灵活的登录呢?
不妨换个角度考虑用户登录。当用户以任意一种方式登录成功后,我们读取到的总是Users表对应的一行记录,它实际上是用户的个人资料(Profile),而登录过程只是为了认证用户(Authenticate),无论是本地用密码验证,还是委托第三方登录,这个过程本质上都是认证。
所以,如果把Profile和Authenticate分开,就十分容易理解了。Users表本身只存储用户的Profile:
id | name | birth等其他字段----+------+-----------------
A1 | Bob | ...
A2 | Adam | ...
而通过用户名口令登录可视为一种Authenticate的方式,利用LocalAuth表维护:
id | user_id | username | password----+---------+----------+-----------
01 | A1 | bob | a1b23f2c
02 | A2 | adam | c0932f32
通过微博登录可视为另一种Authenticate方式,利用OAuth表维护:
id | user_id | weibo_id | weibo_access_token | weibo_expires----+---------+----------+--------------------+---------------
11 | A1 | W-012345 | xxxxxxxxxx | 604800
12 | A2 | W-234567 | xxxxxxxxxx | 604800
如果要添加另一种OAuth登录,比如QQ登录,增加一个表就可以了。不过既然大家都是OAuth家族的,不如统一到一个表,给每家起个名字区分就好了:
id | user_id | oauth_name | oauth_id | oauth_access_token | oauth_expires----+---------+------------+----------+--------------------+---------------
11 | A1 | weibo | W-012345 | xxxxxxxxxx | 604800
12 | A2 | weibo | W-234567 | xxxxxxxxxx | 604800
13 | A1 | qq | Q-090807 | xxx-xxx-xxx | 86400
14 | A2 | qq | Q-807060 | xxx-xxx-xxx | 86400
如果要增加一种新的登录方式,比如SAML,那就再加一种类型的表。
有些网站需要API访问,API可以使用api_key和api_secret来认证,可是怎么把一个API访问关联到一个用户?方法还是增加一种API Auth的表:
id | user_id | api_key | api_secret----+---------+----------+------------
11 | A1 | a-012345 | xxxxxxxxxx
12 | A2 | a-234567 | xxxxxxxxxx
每一种X-Auth表都存储了用户的登录认证信息,并通过user_id
关联到Users
表。这样一来,不但登录过程简化了,而且一个用户可以使用多种方式登录。只要登录成功,拿到了user_id
,最后读取Users
表是为了获得用户的Profile,这样读出来的数据也更安全,因为Users
表不包含用户口令,不会因为暴露API而不小心把口令给泄露出去。
- 基于Metronic的Bootstrap开发框架经验总结(1)-框架总览及菜单模块的处理
- Spring Cloud(六)服务网关 zuul 快速入门
- Docker Registry Server 搭建,配置免费HTTPS证书,及拥有权限认证、TLS 的私有仓库
- Ubuntu 17.04 编译安装 Nginx 1.9.9 配置 https 免费证书
- 基于Metronic的Bootstrap开发框架经验总结(2)--列表分页处理和插件JSTree的使用
- Docker Image 解决镜像无法删除的问题
- Docker Hub 仓库使用,及搭建 Docker Registry
- 基于Metronic的Bootstrap开发框架经验总结(3)--下拉列表Select2插件的使用
- Docker 容器操作
- Ubuntu 17.04 x64 安装 Docker CE 初窥 Dockerfile 部署 Nginx
- 基于Metronic的Bootstrap开发框架经验总结(4)--Bootstrap图标的提取和利用
- WebView 的 input 上传照片的兼容问题
- 在 Linux 上搭建Jekyll静态博客
- 基于Metronic的Bootstrap开发框架经验总结(5)--Bootstrap文件上传插件File Input的使用
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- vue-element-admin上传图片的功能
- Oracle数据误删恢复
- 用斗地主的实例学会使用java Collections工具类
- Command PhaseScriptExecution failed with a nonzero exit code问题解决
- Effective Java中构建器Builder的理解
- Java的位运算符详解实例。
- 用一个测试类简化排序算法时间复杂度的研究
- R语言之可视化(33)绘制差异基因分析统计图
- Java transient不被持久化的原因
- 举一个有趣的例子,让你轻松搞懂JVM内存管理
- gulp的使用
- SpringBoot中 使用[info]日志级别打印mybatis sql语句
- Spring Boot 使用策略模式指定Service实现类
- 55. Vue webpack的基本使用
- ajax无刷新页面切换,历史记录后退前进解决方案