有基础回顾,直接看此图即可:

1. Kerberos简介
1.1. 功能

  • 1. 一个安全认证协议
  • 2. 用tickets验证
  • 3. 避免本地保存密码和在互联网上传输密码
  • 4. 包含一个可信任的第三方
  • 5. 使用对称加密
  • 6. 客户端与服务器(非KDC)之间能够相互验证

Kerberos只提供一种功能——在网络上安全的完成用户的身份验证。它并不提供授权功能或者审计功能。




1.2. 概念

首次请求,三次通信方

  • the Authentication Server
  • the Ticket Granting Server
  • the Service or host machine that you’re wanting access to.

java kerberos认证使用用户名密码 kerberos客户端认证_时间戳

其他知识点

  • 每次通信,消息包含两部分,一部分可解码,一部分不可解码
  • 服务端不会直接有KDC通信
  • KDC保存所有机器的账户名和密码
  • KDC本身具有一个密码




2. 3次通信

java kerberos认证使用用户名密码 kerberos客户端认证_Server_02


        我们这里已获取服务器中的一张表(数据)的服务以为,为一个http服务。




2.1. 你和验证服务

如果想要获取http服务,你首先要向KDC表名你自己的身份。这个过程可以在你的程序启动时进行。Kerberos可以通过kinit获取。介绍自己通过未加密的信息发送至KDC获取Ticket Granting Ticket (TGT)。

(1)信息包含

  • 你的用户名/ID
  • 你的IP地址
  • TGT的有效时间

 Authentication Server收到你的请求后,会去数据库中验证,你是否存在。注意,仅仅是验证是否存在,不会验证对错。
        如果存在,Authentication Server会产生一个随机的Session key(可以是一个64位的字符串)。这个key用于你和Ticket Granting Server (TGS)之间通信。

(2)回送信息

Authentication Server同样会发送两部分信息给你,一部分信息为TGT,通过KDC自己的密码进行加密,包含:

  • 你的name/ID
  • TGS的name/ID
  • 时间戳
  • 你的IP地址
  • TGT的生命周期
  • TGS session key

另外一部分通过你的密码进行加密,包含的信息有

  • TGS的name/ID
  • 时间戳
  • 生命周期
  • TGS session key

java kerberos认证使用用户名密码 kerberos客户端认证_时间戳_03

如果你的密码是正确的,你就能解密第二部分信息,获取到TGS session key。如果,密码不正确,无法解密,则认证失败。第一部分信息TGT,你是无法解密的,但需要展示缓存起来。




2.2. 你和TGS

如果第一部分你已经成功,你已经拥有无法解密的TGT和一个TGS Session Key。

(1) 请求信息

    a) 通过TGS Session Key加密的认证器部分:

  •           你的name/ID
  •           时间戳

    b) 明文传输部分:

  •         请求的Http服务名(就是请求信息)
  •         HTTP Service的Ticket生命周期

     c) TGT部分

  Ticket Granting Server收到信息后,首先检查数据库中是否包含有你请求的Http服务名。如果无,直接返回错误信息。

  如果存在,则通过KDC的密码解密TGT,这个时候。我们就能获取到TGS Session key。然后,通过TGS Session key去解密你传输的第一部分认证器,获取到你的用户名和时间戳。

  TGS再进行验证:

  • 1. 对比TGT中的用户名与认证器中的用户名
  • 2. 比较时间戳(网上有说认证器中的时间错和TGT中的时间错,个人觉得应该是认证器中的时间戳和系统的时间戳),不能超过一定范围
  • 3. 检查是否过期
  • 4. 检查IP地址是否一致
  • 5. 检查认证器是否已在TGS缓存中(避免应答攻击)
  • 6. 可以在这部分添加权限认证服务

TGS随机产生一个Http Service Session Key, 同时准备Http Service Ticket(ST)。

(2) 回答信息

   a) 通过Http服务的密码进行加密的信息(ST):

  • 你的name/ID
  • Http服务name/ID
  • 你的IP地址
  • 时间戳
  • ST的生命周期
  • Http Service Session Key

   b) 通过TGS Session Key加密的信息

  • Http服务name/ID
  • 时间戳
  • ST的生命周期
  • Http Service Session Key

你收到信息后,通过TGS Session Key解密,获取到了Http Service Session Key,但是你无法解密ST。

java kerberos认证使用用户名密码 kerberos客户端认证_Server_04




2.3. 你和Http服务

在前面两步成功后,以后每次获取Http服务,在Ticket没有过期,或者无更新的情况下,都可直接进行这一步。省略前面两个步骤。

(1) 请求信息

    a) 通过Http Service Session Key,加密部分

  • 你的name/ID
  • 时间戳

    b) ST

Http服务端通过自己的密码解压ST(KDC是用Http服务的密码加密的),这样就能够获取到Http Service Session Key,解密第一部分。服务端解密好ST后,进行检查

  • 1. 对比ST中的用户名(KDC给的)与认证器中的用户名
  • 2. 比较时间戳(网上有说认证器中的时间错和TGT中的时间错,个人觉得应该是认证器中的时间戳和系统的时间戳),不能超过一定范围
  • 3. 检查是否过期
  • 4. 检查IP地址是否一致
  • 5. 检查认证器是否已在HTTP服务端的缓存中(避免应答攻击)

(2) 应答信息

    a) 通过Http Service Session Key加密的信息

  • Http服务name/ID
  • 时间戳

java kerberos认证使用用户名密码 kerberos客户端认证_用户名_05

你在通过缓存的Http Service Session Key解密这部分信息,然后验证是否是你想要的服务器发送给你的信息。完成你的服务器的验证。至此,整个过程全部完成。

3.疑问

1)上面有个数据包是KDC经Client转发给Server的,为什么不直接发给Server?

1. 因为Server可能给多个Client提供服务,这样Server需要维护一个Client和会话密钥的对应表,这对Server是一个负担。

2)为什么要发两份关于Client的信息给Server?

. 通过这两份数据的对比,Server就能判断出是不是对的Client在访问服务。

3)Client是如何判断自己在访问对的Server呢?

 1. 因为Client给Server的一个数据包是用Server的master key来加密的所以只有对的Server才能解密。并且server会用server sessionKey加密服务的id,client根据server sessionKey解析得到正是自己访问的服务id即可知道被正确server处理

4)为什么要用会话密钥

1. 通信方的master key是长期有效的,如果在网络上传输,一旦被截取,理论上来说只要有足够的时间是可以破解的。

2. 所以我们才用临时的会话密钥来通信,一段时间后会话密钥会过期,同时时间戳也防止了,恶意用户重复使用同一个数据包。

5)为什么要用时间戳?

1. 如果Client向Server传送的数据包被其他的Client截取,然后自己拿来向Server请求服务这,这样就会出问题

2. Server收到请求后将从解密后的数据包中获得的时间戳和当前时间对比,一旦超过一定范围将直接拒绝请求


4. 参考

http://www.roguelynn.com/words/explain-like-im-5-kerberos/