业务背景
按照惯例,先介绍一下业务背景。
公司有两块比较相似的业务领域,一个是统一登录,一个是三方账户绑定。
统一登录时公司自有业务渠道的登录入口,主要完成帐户登录的鉴权,包括手机号+登录密码、用户名+登录密码、短信验证码登录等。和所有网站的登录站点做的事情一样,不再赘述。
三方账户绑定是指集团其他子公司之间通过身份认证+用户授权绑定实现账户互信,账户首次绑定需要双方做登录鉴权操作,绑定之后只需要第三方账户登陆,用户便可以免登陆的情况下获得我司的登录态权限。简单业务流程如下:
注意:三方帐户绑定服务端是在三方帐户服务 thirdaccount 组件,登录鉴权场景是在统一登录服务 loginservice 组件。前端对应的静态资源也是分开在两个组件上。
问题描述
可以看到‘三方帐户绑定’的过程中,需要做我司帐户登录鉴权,这里的登录鉴权和‘统一登录’场景一样,可以有多种登录鉴权方式。这两个业务场景对于前端来说,页面都类似,流程也一样。
前端同事遇到了疼点:两个相似度极大的模块静态资源存在两份,每次加入新的登录鉴权方式,都需要两边维护,成本较高,因此,前端便希望抽象出统一的页面和前端业务逻辑,配套的前端希望服务端统一提供一个登录接口,这个接口既可以做纯粹的登录,也可以做‘三方帐户绑定’,只需要多送两个:三方业务渠道(channel)、三方帐户标识(thirdAccountNo),服务端的接口判定thirdAccountNo是否有值来决定,在登录鉴权完成后,是否需要做三方帐户绑定。流程简述如下:
但是服务端不赞成这样做,服务端认为这样会造成两个独立的业务领域耦合在一起,弊大于利。矛盾在此。
各抒己见
客户端的观点
1、‘三方帐户绑定’和‘登录鉴权’场景的目标都是为了生成我司帐户登录态,里面的大部分业务逻辑是公共的,除去‘帐户绑定’这一步。因此,可以统一纳入到统一登录服务这个入口完成。
2、从开发和维护成本来讲,后续增加新的登录鉴权方式,只需要更改一套代码就ok了,不需要既更改 thirdaccount 和 loginservice。
服务端的观点
1、从纯粹的业务领域来讲,登录和三方帐户绑定是两个不同的业务领域,不应当将‘三方帐户绑定’纳入到‘登录鉴权’的业务领域。虽然他们最终都得到共同结果——生成我司帐户登录态。
2、从业务安全角度上来讲,不同安全级别的业务应当做隔离。三方帐户绑定这种‘授信’式的鉴权方式安全性相对并不高,很大程度上依赖于合作伙伴的安全性,而登录鉴权作为我司自有的登录入口,我们可以做很多安全加固:图片验证码、帐户锁定逻辑、风控接入等,不同安全级别的业务做隔离的好处在于,出现紧急事件时,我们可以将风险隔离在较小的范围内,这样紧急处理起来牵挂更少。
3、从业务核心维度来看,‘登录并绑定’中的‘帐户绑定’才是我们的核心业务,‘登录鉴权’只是这个核心业务目标中的一个环节,所以‘三方帐户绑定’场景就应当放在 thirdaccount 组件里。
4、从组件依赖上来看,关键路径服务组件 loginservice 不应当反向依赖于非关键路径服务组件 thirdaccount。在反向依赖的情况下,一旦 thirdaccount 组件出现故障,很可能拖累道 loginservice,进而影响到自有渠道的帐户登录。
5、从开发成本角度来看,thirdaccount并不会增加太多的开发和维护工作。在 thirdaccount 提供的‘登录并绑定’ 服务契约兼容‘登录鉴权’服务契约的前提下,thirdaccount只需要在需要鉴权的时候透传请求给loginservice即可,而且如果契约设计良好,及时增加新的登录鉴权方式,也不需要更改thirdaccount。
达成一致
服务端的3、4点理由存在相当的合理性,最终前后端达成一致,服务端不应当将 ‘三方帐户绑定’ 服务合并至 ‘登录鉴权’ 服务,为了配合前端的页面抽象,服务端在 thirdaccount 提供一个新的通用 ‘登录并绑定’ 服务给前端,该服务和现有的 ‘登录鉴权’ 服务契约兼容,前端自行根据是否存在 ‘三方帐户标识(thirdAccountNo)’ 来决定是调用 loginservice 的登录服务,还是调用thirdaccount的 ‘登录并绑定’ 服务, 简要流程和图一保持不变。
心得
1、分清讨论case的核心点,不要被细枝末节干扰。搞清楚业务case的业务目标是什么?这个目标就是你的业务核心点,就像 ‘登录并绑定’ case,既有 ‘登录’ 又有 ‘绑定’,但是 ‘绑定’ 才是核心点,‘登录’ 是为了 ‘绑定’ 而做的,‘绑定’ 才是我们的业务目标;
2、关键路径服务尽量少依赖其他服务,尤其是非关键路径服务。例如本例中的 loginservice 不应当依赖于 thirdaccount;
3、不要为了眼前的便利做过度的抽象,后续可能的业务变化会让过度抽象成为镣铐。比如如果这次将 ‘三方帐户绑定’ 并入到 ‘登录鉴权’ 服务中,现在看来一个服务搞定了,但是假如后续有一个三方渠道不在 thirdaccount 服务组件中处理,那么loginservice就需要再次依赖其他业务组件,需要更改抽象出来的公共服务,最后适得其反。