1.首先思考下实现这个的登录系统的目的:
- 1 . 能结合国内的行情,支持手机,账号,等第三方登录。
- 2 . 易于扩展,能往多应用进行扩展。
2.主要需要解决的问题:
- 1 . 账号体系的设计
- 2 . 数据库表的设计
- 3 . 登录流程的设计
2.1 思考一:账号体系的设计
这里我们主要以
自建账号为主,第三方账号为辅
。
2.1.1:自建账号和第三方账号如何结合?
回答:无论自建账号还是第三方登录时,注册时都生成唯一的ID,这个ID不可修改,所有的第三方登录,邮箱,手机号,都绑定在此ID之下。
2.1.2:ID如何生成,如何设计,如何确保唯一?
回答:
- 1 . 我们可以使用mysql中的自增id。 缺点
- 2 . 使用uuid。
- 3 . 使用Twitter使用Snowflake算法。
例子:
- 微信登录:wechat_xxxx
- 手机登录:phone_xxxx
- 账号密码登录:local_xxx
- 优点:本地生成,简单,性能好。
- 缺点:长度比较长,不方便查询。
2.2登录流程的设计:
2.3 数据库的设计
模型应该把用户的个人信息和身份区分开来,身份用于验证和登录,个人信息归于个人资料,另行处理。
个人资料表:
- 用户唯一的ID
- 基本信息:昵称,性别,城市,头像。
- 微信:绑定的微信账户
- 支付宝:绑定的支付宝账户
账号密码表:
- 用户唯一的ID
- 账号:大小写字母下划线数字组成
- 密码:密码+uuid+盐 MD5加密。
- 邮箱:符合邮箱规范。
- 注册时间:时间戳
第三方社交登录表:
- 用户唯一的ID
- 第三方的识别码
- 第三方的平台
- 创建时间:时间戳
2.4 前后端的鉴权方式设计。
常见的几种鉴权方式
- HTTP Basic Authentication
- session-cookie
- Token 验证
- OAuth(开放授权)
这里我们选用Token验证,常用的JWT。
Token验证的好处:
- 相比在服务端效验sessionID的有效性,TOken本身就是一种登录凭证,需要效验是否合法即可。
- 相比cookies-session,Token验证支持更多的客户端类型。
- 更易于扩展。
2.4.1 Jwt验证会遇到的几个问题:
废除问题:
- Token一旦签发了,在有效期内都可以使用,服务端无法终止和废除。
续签问题:
- 无法像session那样, 自动更新sessionID的有效期。
解决方法是:参考OAuth2中个的refreshToken,允许客户端主动刷新Access Token
流程:
- 客户端首先进行认证。
- 服务端效验后 ,生成两个Token:Access Token 和Refresh Token,一个有效期短,一个有效期长。
- 客户端访问受限资源时,携带access Token,进行鉴权。
- 如果Access Token 没有过期,则返回数据。
- 如果Access Token 过期,通知客户端使用Refresh请求刷新接口,刷新accessToken。
- 如果Refresh Token 没有过期,服务端下方新的Access Token,客户端通过新的Access Token 请求数据。
- 如果Refresh Token 过期,同时access Token也过期,那么让用户重新登录。
这样的好处在于,用户不会频繁的隔几个小时就需要登录一次,但Refresh Token有效时长是固定的,假设是两周,那么用户两周就需要登录一次。
对Refresh Token的改进
- 可以在用每次请求更换Access Token时,判断Refresh Token的剩余时长,若小于25%,则延长一个Access Token的时间。
如何同一时间,允许在一个设备登录?
- 我们在缓存中维护一个黑名单表,同时jti是每个token的唯一标识符。
- 新设备登录时,更换Token的时候把旧的Token加入到黑名单中。
- 旧的token请求时,由于在黑名单表中,判定为无效。
定时清理黑名单中过期的Token,防止缓存表太大。
参考文章
- 前后端常见的几种鉴权方式(小结)
- 基于 JWT + Refresh Token 的用户认证实践
- 设计一个可扩展的用户登录系统 (1)
- 设计一个可扩展的用户登录系统 (2)
- 设计一个可扩展的用户登录系统 (3)
- JSON Web Token 入门教程