单点登录之各自为证

719 阅读6分钟

单点登录的目标

很久以来,对于同一个用户在多个系统间切换问题,都会用‘单点登录’这个说法来表示“一次登录,到处通行”的美好愿景。

尽管这个说法并不严谨,但是目标是明确的:用户标明了身份,你们(有关联的若干系统之间)应该都知道来者何人。(本文主要探讨认证部分的内容,授权相关的内容没有涉及)

单点登录场景:统一登录与各自为证

理想的场景是,公司有一整套IT系统的系统,登录所有系统都使用同一个账号,然后无论是跳转也好,邮件内的安全链接也好,都可以顺畅的工作。(场景A)

还有一个希望使用单点登录的典型场景是:公司越做越好,人越来越多,IT系统也越来越庞杂。老系统,新系统,交织在一起。此时希望的方式是:从任何一个系统登录,都可以顺畅的(无感登录)其它系统。(场景B)

这两个场景略有区别。

场景A:用户访问任何系统时,被引导到统一用户管理服务,进行认证。各个系统只认它给出的认证,才提供对应的服务。

[注1]: 这个图只是示意图,忽略了不少细节,不要作为设计和实施参考。
[注2]:粗线条表示‘我是个有身份的人了’,腰也粗了,声音也大了...

场景B:用户访问任何系统时,首先是该系统完成自己的认证,然后再换取统一认证令牌。这个场景里,系统ABC具有和‘统一访问管理’相同的认证优先级。这个场景,我暂且称之为“各自为”。

各自为证 的现实需要

此场景不是通常说的单点登录的典型场景。维护成本也高,又复杂,但是在没有选择的情况下,还是要考虑支持。 例如:

要求使用微信自动登录后,可以在各个系统之间免登陆。

因为你不可能改造微信,让它转而支持本公司的登录服务,所以你需要按集成接口完成微信登录后,换成公司的IT系统群所承认的统一登录令牌。

  • 典型的统一登录场景类似于:去住酒店的时候,拿身份证就可以了。
  • 各自为证的场景类似于:你丢了身份证的时候,拿单位介绍信(现在还有这个吧?)去住酒店(介绍信上有你的身份证号码)

这个模式其实并不陌生,证书链就类似。

统一登录和各自为证的内在一致性

回归原始的认证‘刚需’,业务系统其实不关心认证的过程是怎样的,它只关心两个:1-认证的结果;2-做认证的服务的可信度。

  • 最简单的单系统登录认证,问题1是通过校验自己内部数据和用户输入的数据一致否来判断;问题2是自己肯定信任自己;
  • OAuth,问题1通过令牌表示认证完成;问题2则是(经过一些系统外工作,了解后无条件)直接信任认证服务提供方。
  • SSO,问题1通过ticket表示认证结果;问题2则是直接信任认证服务方,因为这些服务都是事前约定的。

所以,统一登录和各自为证的本质是一样的,只是各自为证的认证服务提供方不是一个唯一的服务,而是一组有层次的服务(类似代理商、军代表、大使馆),而且恰好其中之一是和当前的业务系统部署在一起的。

先假设一个应用场景

  • 某公司成立之初,有一套工作量统计系统W,每个工人登录后,提交每日完成的工件数量,消耗的材料等;
  • 生意越做越大,开了很多门店直接销售,就又建了一套销售统计系统S,销售员们记录各自的业绩,以及下个生产周期的订货量;
  • 人多了,HR就建了一套系统H,管理工资啊,请假啊;给大家建了账号,可以查询和请假。
  • 智能手机普及了,大家都说,用微信小程序吧,日常工作其实不需要复杂的录入,手机多方便!

于是,需要一套统一登录的法子,不然好麻烦

需要的数据关系

  • 微信小程序
    • 能做什么:此人是微信openid为W1,绑定手机号为1xx的人
    • 要做什么:此人在W,S,H系统中分别对应谁啊?我要把他的工作量记录,销售记录,工资表调出来啊!
  • W系统
    • 能做什么:此人是工人E1,手机号1xx
    • 要做什么:诸位兄弟系统请周知,此人我们确认过的工人E1,手机号1xx,到贵系统后,请给与协助。
  • S系统,H系统:类似W的情况,略

总结一下:每个系统知道当前用户在本系统内部是谁,需要确定他在其他系统是谁。

正值新冠肺炎抗疫,我们以两位医疗界人士举例这个数据关系。

  • 在 中国 ,她是一位公民,李兰娟,身份证号XXX
    • 在 中华医学会 是 副会长,身份ID XXX1
    • 在 中国工程院 是 院士, 编号XXX2
    • 在 伦敦皇家内科医师学 无记录
    • 在 微信 是 实名认证用户,openid XXX3
  • 在 中国 ,他是一位公民,钟南山,身份证号YYY
    • 在 中华医学会 是 2006-2011届会长,身份ID YYY1
    • 在 中国工程院 是 院士,编号YYY2
    • 在 伦敦皇家内科医师学会 是 会士,身份ID YYY3
    • 在 微信 是 实名认证用户,openid YYY4

这种结构的数据,比较常见的处理方式是使用LDAP。

在我们的场景中,就可以这样处理(忽略授权相关问题):

  • 微信小程序说:他是 YYY4 的实名认证用户,所以他是‘中国’区用户YYY
  • 微信小程序向W请求:请提供‘中国’用户YYY的工作量记录
  • W回应说:他是我系统YYY1用户,工作量记录请见附件
  • 微信小程序向S请求:请提供‘中国’用户YYY的销售记录
  • S回应说:他在我系统无记录
  • 微信小程序向H请求:请提供‘中国’用户YYY的工资表
  • H回应说:他是我系统YYY2用户,工资表请见附件

实现的考虑

核心问题搞清楚了,实现的手段可以各显神通。

我们团队使用的DaaS系统,自动生成的各个模块,都已经实现或即将实现微信登录,LDAP,手机号登录等多种登录方式。新开发的系统已经天然支持了单点登录。