我想在Java中使用Kerberos实现单点login,并已成功地使用Windowslogin中的故障单创build了服务的故障单。 不幸的是,我只能在启用registry项“allowtgtsessionkey”时创build该票证。 我收到一个exception,只要我禁用它,消息“标识符不符合期望值(906)”。 registry项logging在http://java.sun.com/j2se/1.5.0/docs/guide/security/jgss/tutorials/Troubleshooting.html和http://support.microsoft.com/kb/308339上 。
不幸的是我没有访问我的应用程序将被使用的计算机上的registry,所以我正在寻找一种方法来做到这一点,而不必修改它。 当我在Internet Explorer或Mozilla Firefox上通过SPNEGO进行单点login时,他们会在我的票据caching中创build一个服务票据,所以肯定有办法在不设置registry项的情况下执行此操作。 有没有人有一个想法如何在Java中做到这一点?
感谢您的帮助,memminger
更新:我放弃这个问题。 Windowsregistry项禁止访问Ticketcaching内的票证(更确切地说:主体)。 Windows上的Java使用自己的GSSAPI实现,我想这需要访问票证来创build一个服务票据。 SSPI Windows API可以完全访问Ticketcaching,因此可以创build服务票据。 这个API被Web浏览器使用,但是它没有被Java使用(根据http://java.sun.com/developer/technicalArticles/J2SE/security/#3 )。 当我在访问过一次网页后禁用了SSPI(所以创build了一个服务票据)后,我仍然可以访问这个页面,所以使用命令行实用工具就足以使用SPPI API创build服务票据了。
对于我们来说,这意味着我们可以放弃单点login(这对我们来说是不可接受的),或者我们在应用程序的客户端进行authentication(因为我们只能读出用户名,而不能validation服务器),这是一个重大的安全风险。 另一个例子是安全约束越强,安全漏洞就越大,因为它们变得太复杂了。
原谅我,如果我误解你的问题,但…
SSO类型系统的要点是,客户端直接向(单独的)验证服务器进行身份验证,并从中获取票证。 然后它将票证传递给它想要使用的目标服务器,每个目标服务器都会验证票证是否与认证服务器一致。 如果票证被验证,则服务器可以假定客户端只通过提供具有可接受凭证的(可信)Kerberos服务器来获得它。
在这个过程中,任何服务器都不应该代表客户端进行身份验证。 在这样的系统中,唯一需要知道和验证客户端凭证的服务器就是认证服务器 – 其他服务器不需要访问这些信息。 通过这种方式,客户端只需进行一次认证交换就可以对许多服务器进行认证,而且凭据不会被存储在多个服务器上,也不会被多台服务器访问。
这听起来像你的实现工作正如它应该 – 认证应该发生在应用程序的客户端,这是正确的,而不是一个安全风险。
你有没有尝试在Java 6中设置sun.security.jgss.native? SSPI不是Windows的“原生”界面吗?
您可以通过JNA访问本机SSPI API。 有关示例,请参阅WAFFLE中的WindowsAuthProviderImpl或Apache HC库中的WindowsNegotiateScheme 。