如何针对 Java 中的服务器验证 Kerberos 票证?

我们使用JAAS在使用Windows Kerberos票证缓存的Java应用程序中启用单点登录。我们的 jaas.conf 配置文件如下所示:

LoginJaas {
  com.sun.security.auth.module.Krb5LoginModule required
  useTicketCache=true
  doNotPrompt=true
  debug=true;
};

这样,我们可以创建一个Jaas LoginContext并成功获得用户的Kerberos票证。我们使用 JMI 将此票证发送到服务器应用程序。但是,我们没有设法在服务器上验证Kerberos票证实际上是由我们的Active Directory创建的。

目前,我们通过简单地检查服务器主体(KerberosTicket.getServer())名称是否在领域部分中具有我们的域名来对票证进行非常不安全的验证。但是,当然,任何人都可以设置一个具有相同领域名称的自己的 Kerberos 服务器,并使用该票证启动应用程序。

我发现的一个想法是使用Kerberos票证对Active Directory LDAP进行身份验证。不幸的是,我们使用Windows 7,并且仅在设置注册表项时才可以使用Kerberos票证来针对LDAP进行身份验证(请参阅 http://java.sun.com/j2se/1.5.0/docs/guide/security/jgss/tutorials/Troubleshooting.html,搜索 allowtgtsessionkey)。这对我们的用户来说是不可接受的。

有没有办法根据我们的Active Directory服务器验证票证?我怀疑有一种方法可以检查KerberosTicket.getServer()票证是否等于我们服务器的票证,但我不知道如何做到这一点。更新:KerberosTicket().getServer() 只返回一个 KerberosPrincipal,除了服务器票证名称和领域之外,什么都不包含,因此它不适合验证。

感谢您的帮助,梅明格


答案 1

正如你所提到的,解决这个问题的正确方法是对服务进行 kerberbering,这是 Kerberos 协议(针对服务器对客户端进行身份验证)的全部意义所在。票证重用并不完全有效,因为如果确实如此,那将是一个安全问题。Kerberos服务不需要“登录到Active Directory”,它只需要与AD共享一个密钥。

顺便说一句,要使用JAAS获得SSO需要设置该 allowtgtsessionkey,在Windows上没有办法解决这个问题。


答案 2

由于似乎没有人真正知道这个问题的答案,我想我们必须从我们的服务器应用程序中制作一个适当的Kerberos服务。登录到 Active Directory 本身并正确设置了 ServicePrincipalName 属性的一个。有点像SPNEGO对HTTP所做的那样。一个很好的起点是SourceForge上的SPNEGO Servlet过滤器(http://spnego.sourceforge.net/)。http://thejavamonkey.blogspot.com/2008/04/clientserver-hello-world-in-kerberos.html 也是如何进行服务登录的一个很好的例子。不幸的是,这导致了注册表项的相同问题,所以我发布了一个新问题,即Java或命令行实用程序中是否有办法使用本机SSPI API获取服务的Kerberos票证?


推荐