在 Windows 和 Linux 上使用 Kerberos 的单点登录

SSO using Kerberos on Windows and Linux

我们有一个内部开发的基于 client/server 的应用程序。客户端和服务器通过 TCP/IP 连接与特定于应用程序的协议进行通信。 Windows 上的客户端 运行 和 Linux 上的服务器 运行。所有机器都在同一个Active Directory/Kerberos domain/realm.

目前,用户在启动应用程序时输入用户名和密码。服务器检查用户名和密码(身份验证)。根据用户名,服务器还确定对资源的访问权限(授权)。

我们想为应用程序添加单点登录 (SSO) 功能。也就是说,我们不希望用户输入用户名和密码,但我们希望自动登录为当前 Windows 用户。

当然,必须安全地确定当前 Windows 用户。

我想出了以下设置:

  1. 我在 Windows 上使用 SSPI(协商),在 Linux 上使用 GSSAPI。
  2. 当客户端连接到服务器时,它使用 AcquireCredentialsHandle (Negotiate) 获取当前 Windows 用户的凭据。
  3. 客户端使用 InitializeSecurityContext (Negotiate) 根据这些凭据生成令牌。
  4. 客户端向服务器发送令牌。
  5. 服务器使用gss_acquire_cred()获取服务的凭据。这些存储在 .keytab 文件中。
  6. 服务器从客户端接收令牌。
  7. 服务器使用gss_accept_sec_context()处理令牌。此调用还 returns "source name",即客户端的当前 Windows 用户。
  8. 服务器使用"source name"作为用户名:服务器不执行额外的身份验证。服务器仍然执行授权。

这可行,但我有一些问题:

  1. 这安全吗?它 不应该 客户端可以指定除客户端进程的 Windows 用户之外的任何其他用户名。如果用户拥有作为另一个用户(合法或非法)创建进程的凭据,则不允许这样做。
  2. 我应该执行额外的检查来验证用户名吗?
  3. 是否有其他方法可以在此设置中实现 SSO?它们的优缺点是什么?

您在此处描述的是对用户进行身份验证的正确方法。您不必担心用户会指定不同的名称;这就是 Kerberos 为您处理的事情。

如果客户端能够获得服务票证,那么他们一定能够通过 KDC (Active Directory) 进行身份验证。 KDC 创建一个包含用户名的服务票证,并使用服务的密钥对其进行加密。

客户端将无法使用假名称为服务器创建票证,因为它没有必要的密钥来加密票证。

当然,这一切都假定您已正确设置所有内容;例如,客户端不应该访问服务的密钥表文件,并且服务在其密钥表中不应有任何主体,除了它自己的。

关于它的工作原理有一个非常详细的解释 here