37dad0b1504c66574fa761a0fc0c8c00
跟 Kerberos 学写技术文档

毫无疑问,官方文档,是我们开始学习一门新技术,最初也最重要的资料。然而,做技术的人,往往是重视代码胜过一切,所以大部分项目、产品的文档,都是很糟糕的。

今天,我想以 Kerberos 为例,看下一篇优秀的文档,应该是怎样的。

首先搞清楚两个完全不同的概念:认证和鉴权。

  • 认证,英文是 Authentication,解决的问题是,证明你是你声称的人。比如你得提供用户名和密码,校验成功了,才认定你就是谁谁谁。

  • 鉴权,英文是 Authorization,解决的问题是,检查你这个人有什么权限,能干嘛。比如你只有读一张表的权限,那就不能让你写。

Keberos 就是一套认证的方法和实现。

为什么要新做一套认证方法?肯定是已有的不够好,用户名+密码这样的方案虽然简单,但有很多安全隐患。

下面我们就看看,Kerberos 是怎么解决这些隐患的。原文 自然是英文,以戏剧的形式推进,我这里只提炼要点,不逐字翻译了。


1

A 和 B 在各自的终端上操作。

A: 受不了这个分时系统了,一堆人登录进来,不停被中断,我都干不了活了。就应该给每个人配台独立的工作站。

B: 先不说得花多少钱。工作站的硬盘那么小,那么多软件,都装不下。

A: 我早想好了,弄几台机器专门放软件,每个人登录工作站之后,自动去这些机器获取软件。省空间,更新软件也方便。

B: 还有打印机、邮件那些呢?

A: 都类似,弄些共用的专门的机器,每个人从自己的工作站登录上去,再去打印文件、发邮件等等。

B: 听起来不错。但是我忍不住要想干点坏事,我就偷看到你的用户名,然后在我自己的工作站上登录,就可以偷看你的邮件了。

A: 好像还真是...... 我再想想。

2

第二天。

A: 我想到办法阻止你这种人冒充别人了。

B: 说来听听。

A: 加个密码。你以一个用户的身份发起请求后,服务器找你要密码,你输入后,服务器检查,用户名和密码不匹配就拒绝请求。

B: 嗯,听着可以。但是每台服务器都需要保存所有人的密码,这个更新成本就很高了。

A: 简单,把这个功能也抽出来,做成一个独立的中心化的认证服务。所有的用户名密码都只保存在这个服务里。并且这个服务对用户和其他服务一视同仁,谁都不相信,所有用户和服务的密码都保存在数据库里。

B: 似乎行,那现在的流程是怎样的?

A: 比如你想发一封邮件,就需要向邮件服务器证明你的身份。

你先向认证服务提供你的用户名密码,认证服务和保存在数据库里的用户名密码比对,发现能匹配上,就相信了你的身份。

认证服务就可以向邮件服务担保你的身份。怎么担保呢,要提供些东西给邮件服务。最简单的当然是直接提供邮件服务的密码给你,但这样肯定不行,你以后就会绕过认证服务器直接访问邮件服务了。

所以这样,认证服务给你发一个 ticket,内容是你的用户名,然后用邮件服务的密码加密。你拿到这个 ticket 之后,发给邮件服务请求服务。邮件服务用自己的密码解密,拿到用户名,和你声称的用户名做对比,如果一样,就相信你就是你,然后就可以帮你收发邮件啦。

B: 嗯,大致懂了。但我有些问题。目标服务怎么知道自己的解密有没有问题呢?比如我拿一个服务的 ticket 去使用另一个服务?

A: 还真没想过这个问题。

B: 能不能这样,在 ticket 里面加上目标服务的名字。

A: 好像行。所以 ticket 大概会是这样:ticket - {username:servicename}

B: 嗯,然后用目标服务的密码加密。但是好像还是不够安全。如果我在网络中截获了这个 ticket,然后在邮件客户端里,用这个 ticket 对应的人的用户名去发请求给目标服务,就能冒充这个人了。

A: 还真是。

B: 可以这样,再加一个 IP 地址。目标服务解密 ticket 后,除了校验用户名,还要校验下 IP,有一个不符合,就是冒充的。

A: 对啊,一样的思路。所以这个时候 ticket 的格式是 {username:address:servicename}。

B: 嗯功能上是完整了。但是用户体验不太好。每次我想要用一个服务,都得去获取一次 ticket,挺麻烦的。

A: 那就复用 ticket,不用每次都申请。

B: 这样是行,但是如果我要用其他服务呢,还是得去输入密码拿 ticket,并且,我的密码是明文发送给认证服务的,一旦被截获,就一点安全都没有了。

A: 这还真是个要命的问题,得好好想想。

3

A: 我想到办法了。

B: 真的吗,好快。

top Created with Sketch.