前言
由于没事喜欢自己瞎鼓捣,写一些感兴趣的项目,虽然三天打鱼两天晒网,项目一直没写出来,但是野心倒是挺大的,规划中有几个小项目想写,每个项目都会有登录系统,如果每个项目的登录系统都写一遍,肯定是太过麻烦的,而且不容易把几个项目关联起来,于是就想几个项目通用一套账号系统,就类似于腾讯系应用一样,一个QQ号可以登录腾讯游戏、腾讯视频、腾讯音乐等。在网上搜了很久,可能是搜的方法不对吧,搜到的大都是讲的多点登录的,总之就是没搜到完全符合我需要的解决方案,但是也不能说完全没有用,于是自己结合搜到的知识点又加上自己摸索,就总结了一套自己的账号体系,出于交流和学习的目的,来和大家分享一下
由于我作为一个初学者,也接触不到大公司成熟的解决方案,自己思考的想法肯定不成熟,希望各位兄弟不要嘲笑,如果有什么好的方案希望能多多指点。本篇文章还是以思路为主,如果有人对代码实现感兴趣也可以评论区留言,也可以进我主页关注我公众号加我个人微信进行交流。
需求
首先来理一下我们具体的需求
- 一个账号可以登录几个系统(应用)
- 几个系统(应用)之间互不关联,登录状态互不影响,一个系统的退出和登录不影响另一个系统
- 可以手动的控制所有系统的登录状态(如修改密码时所有系统退出登录)
上面就是我们最基础的需求,分析需求可知我们需要一个账号中心,如下图所示:
实现
基础登录实现
最开始要写的肯定就是最基本登录功能,登录功能就是采用的最简单的jwt登录方案,用户输入账号密码或者验证码发送到账号中心,账号中心进行验证,验证通过后向客户端返回token,并把token存储到redis中,这样就实现了最简单的登录功能。这里虽说用的账号是同一套账号,但是考虑到多个应用的风格不同,所以账号中心不提供统一的登录页面,每个应用都有自己的登录页面,调取账号中心的登录接口即可。
上面说的是常规的登录流程,但我们要实现的是从业务系统登录到账号系统,在这个流程中账号系统是作为一个第三方,最终处理还是要落实到业务系统上的,所以我们需要对上面的流程进行改造,我这里的处理方法是这样的。
如上图所示,我们登录的时候先调用账号中心的登录接口,之后账号中心验证登录信息,验证通过,则把token存入redis中并返回给应用客户端,应用客户端又拿这个token去请求应用服务端,应用服务端又拿这个token去账号中心验证,验证通过则返回客户所需信息,所以这里我们的鉴权其实是放在账号中心的,应用每次请求,应用服务端都会去账号中心鉴权,这样设计可以让账号中心实时的控制每一个应用的登录状态,我也不知道这样设计对不对,如果不对希望大家可以指正。
多应用登录时如何区分
我这里设计的是应用客户端登录和应用服务端验证的时候,都会传一个这个应用的唯一标识的,账号中心存储时,会在redis中存储一个哈希值(hash),哈希值我理解的就是一个对象,哈希值的名称为该账号id,里面的字段名就是应用唯一标识,字段值就是该应用的token。
应用内的账号系统
虽然我们有了账号中心,但每个业务也需要有自己的账号系统,业务内的账号系统主要存储一些用户个性化的头像、昵称和该应用独有一些属性,账号中心存储的主要为手机号,账号绑定关系等敏感信息。关于应用内的登录逻辑处理,我是这样处理的。
此处逻辑以node.js中的处理逻辑为例
上面是应用内的登录逻辑,这里的登录我们是用查询用户信息的接口做的,查询用户信息的时候判断应用内存不存在账号id绑定的用户,存在就返回,不存在就创建用户并返回。由于获取用户信息接口是放在白名单中的,下面展示一下不在白名单中的其他接口是如何鉴权的。
这里提一嘴吧,应用内有自己的用户表,每条用户信息有自己的userid,绑定的有账号id(accountId),一般只有在登陆或者涉及到账号中心的操作时才会使用账号id,一般情况下,在应用内处理业务逻辑时使用的都是userId。
关于登录这块就到这了,如有疑问,欢迎留言