平台化服务的基石:用户认证模型设计

发布于: 2020 年 05 月 27 日
平台化服务的基石:用户认证模型设计

用户权限(IAM)可以说是平台化建设最基础的服务,该服务建设的好差直接关系到平台化建设的成败。而用户及认证体系的设计更是基础中的基础,可谓是牵一发而动全身。本文我们以问题导向,聊一聊用户认证模型的设计。

基本概念

身份识别与访问管理(IAM,Identity and Access Management)包含了四个重要概念:

  • 认证(identification):确认访问者的身份,可通过用户名+密码, 手机号+验证码等方式,常见于登录操作

  • 授权(authorization): 为访问者委派权限并返回凭证,常见于Token形式

  • 鉴权(authentication): 根据访问者凭证确定访问者身份,常见于基于请求Token找到对应的账号

  • 权限控制(permission control): 根据访问者的权限配置及访问对象判断权限合法性,常见于基于ACL/RBAC模型扩展实现权限管理

这四个词在后文会经常提及,不要混淆。

用户隔离

作为平台服务需要支撑不同的组织粒度,比如不同的部门、业务线、公司,而不同组织粒度对用户信息有不同的隔离要求,比如一般而言,不同公司之间用户是隔离的,即用户U1在公司C1与公司C2下是两个独立的对象,可以有不同的密码、不同的个人信息,再如一般而言同一公司不同业务线间用户应该是共享,用户U1在业务系统S1中改了密码那么在同一公司的业务系统S2中也会修改。

这时我们就引出用户模型最基础的概念:租户、应用。

租户(Tenant)是数据隔离单位,不同租户间的数据不能共享(也有例外,后续文章会涉及“超级租户”)。一个租户可以有多个应用,应用(App)面向业务系统,一般而言,一个应用对应于一个业务系统,但并不强制这种一对一的关系。账号(Account)隶属于租户,即便是同一个自然人在不同租户间也会有各自的账号,同一租户的不同应用共享账号信息。

上表可知,张三在T1、T2租户下是两条记录。

差异化认证

不同的产品可能会有不同的认证方式,如产品P1需要支持用户名+密码、微信OAuth,产品P2需要支持用户+密码、手机号+验证码等。

这时我们会引入两个对象:账号认证(AccountIdent)及 账号认证配置(AccountIdentConfig),一个账号可以有一个或多个认证项,每个应用可以配置不同的认证项。

如上表,A1应用有三种认证方式,A2只能用手机号+验证码。

如上表,张三在A1应用下添加了两个认证,用户名+密码时AK为用户名,SK为加密后的密码,手机号+验证号时AK为手机号,SK为空(验证码多存储在缓存中)。

Note:对于 用户名/身份证/工号+密码 登录的方式本模型有一定缺陷,需要存储三行记录,每种AK对应的SK(密码)以不同,但如果要相同时需要有复制逻辑,指定一个基础认证作为复制的源头。

Tip:为什么不把AK写到Account表

在架构原则中说明了平台服务要支持不停服部署,而不停服的一个要求就是数据模型的稳定性,即使是对表加一个字段都可能导致服务暂停(MySQL需要有DML写锁,在有查询或事务在进行时可能导致表不可读写)。

认证类型有多种,要求可扩展,故不能写入到Account表。

多端登录

应用A有PC版、APP版,要求APP和PC用户可以同时在线

应用B只有PC版,要求同一时间只能在一处登录

应用C也有PC版本、APP版本,要求PC上只能在一处登录,但PC登录时不能把APP的登录挤下线

这里加了账号凭证配置(AccountCertConfig),一个账号可以有一个或多个凭证,一般而言凭证对应的是Token。

这个模型的核心是将凭证分成多种类型(Kind),每种类型拥有包括保留版本数量、有效时间在内的个性化设置。

上表配置了两种凭证类型,每个凭证类型各保留一个版本,即APP上同时只能有一个终端在线(不允许在多个手机上登录),PC上也同时只能一个终端在线,但允许APP与PC同时在线。

上表只配置了一个凭证类型,并且只保留一个版本,那么无论什么类型的终端同时一时间只能有一个终端在线。

Tip:凭证类型是登录时由前端(更灵活)或服务端(更安全)传入的,可由业务上自定义。

上表配置的含义是默认(业务上传入Kind = ALL)t1租户允许同时有3个终端在线,但对APP1这个应用而言允许PC、IOS、ANDROID各终端(业务上传入Kind = APP1_PC / APP1_IOS / APP1_ANDROID)各自只能有一个终端在线。

子父账号

用户权限中心要求支持RAM( Resource Access Management)用户,RAM用户的权限是其所属账号的子集

业务上可能需要由某账号临时代替另一个账号做一些操作,比如领导休假,他的一部分审批权限要临时给到某个下属,另一部分的审批权限要临时给到另一个下属

这个需求不需要添加模型,只要在账号(Account)模型下添加两个字段即可:

  1. openId,给业务方使用,用于标识账号唯一性的字段

  2. parentId,父账号Id

Tip:一般而言,不会将账号表的Id(数据库主键)给到业务方,一方面在做分库分表操作时Id可能变更不够稳定,另一方面暴露了内部关系不够安全,所以更倾向于使用openId,openId可以是UUID也可以自定义业务表达。

这一模型的核心是:

  1. 业务方以openId与用户权限中心交互

  2. 子父账号Id不同,但openId相同

  3. 无论是父账号还是子账号都拥有完整的认证、权限关联,不同之处在于给子账号授权时只能授予父账号权限子集

上表有2个父账号,2个子账号(关联账号1),由于子父账号有完善的权限关联,所以很容易实现RAM用户功能要求。

有意思的是这一模型实现了2个维度的账号识别:

  • 由于子账号、父账号都有独立的认证方式(子账号拥有独立的手机号、用户名等)所以子父账号间Token不同,故站在用户权限中心的角度可以区分当前是哪个账号操作

  • 子父账号的openId相同,故业务方无法感知当前是子账号还是父账号在操作(如果需要区分时可以拿Token向用户权限中心换取账号信息)

这种 多维用户识别 带来了很大灵活性,比如上面审批需求。正常情况将自己的审批权限给某人需要在审批系统上实现“指派”功能,指派还要限定时间、范围,到期后还要回收。但有了多维用户识别后领导可以把自己部分权限给到某些子账号,用户权限中心可以区别子父账号,所以子账号登录后在用户权限中心能获取到可审批的权限;业务系统记录的是openId,子父账号openId相同,所以在业务系统上视为同一个人,这样业务系统几乎不需要改动就可以完成上述的功能需求。

应用认证

需要有能鉴别不同应用身份的方式,以对各应用做相应的权限管控。

这就是最常见的应用认证(AppIdent)模型,每个应用有一个或多个认证实例,这里的AK/SK就是大家熟知的Access Key Id/Secret Access Key,每个应用创建时生成一组默认的AK/SK,管理员也可手工创建多组AK/SK,将不同的AK/SK给到不同的服务以实现更细粒度的权限管控。

小结

本文我们简单地介绍了用户权限中心的用户认证模型设计,涉及了几个核心的点,但一个真实的、可用的模型会比本文介绍的复杂很多。

在后续的文章中,笔者会陆续介绍诸如用户权限中心的权限、用户触达中心(消息中心)、数据共享中心、规则中心、风控系统等相关的模型设计。

关注我的公众号:

发布于: 2020 年 05 月 27 日 阅读数: 4
用户头像

孤岛旭日

关注

努力成为一个好爸爸、好丈夫。 2018.10.30 加入

10年前,毕业时,芳华正茂,立志Coding完美世界,10年后,35,志向未成但理想依旧,勉励之、践行之。

评论

发布
暂无评论
平台化服务的基石:用户认证模型设计