我们有一个可以与外部服务通信的服务器端应用程序。这取决于我们的配置,我们是否通过使用预先配置的凭据调用我们的用户凭据来验证这些服务,或者根本不对。
外部服务可能使用HTTP协商身份验证。对于我们的自定义HTTP / WebDAV请求,我们使用Apache HttpClient,我们在自己的控制下处理凭据。但是对于JAX-WS调用(或第三方库调用的普通HTTP URL),Java的HttpUrlConnection处理身份验证本身。这是事情变得奇怪的地方。
Java应该总是尝试使用当前主题的Kerberos凭证进行协商。那很好,而且很有效。它也可以使用票证缓存(即kinit会话或系统会话,如果可访问),但如果我正确阅读文档(*),它应该只在两个条件下这样做:
*)https://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/lab/part6.html
这不是发生的事情。在我们可重现的测试中,如果主题为空,则默认始终使用系统凭据。更糟糕的是,显式设置useSubjectCredentialsOnly为true(应该是默认值)不会改变此行为。到目前为止我们发现的唯一解决方法是明确提供一个自定义JAAS配置,它将useTicketCache设置为false(这也应该是默认值)。
调试Krb5LoginModule表明,除非我们配置此变通方法,否则登录模块实际上会使用useTicketCache = true进行调用。
我们可以在所有Windows系统上重现这一点。似乎Linux可能表现良好,但我无法详细验证这一点(由于域名问题)。
我读错了文档吗?或者Java实现中是否存在错误?或者我们的Windows系统是不是很冒险?
我们应该告诉客户始终配置一种解决方法以防止Java使用服务用户的凭据而不是将请求发送到我们服务的用户秘密调用远程服务,这似乎非常不理想。 / p>
答案 0 :(得分:2)
至少在我刚刚调试的Java 8 u 131代码中,函数sun.security.jgss.GSSUtil.useSubjectCredsOnly(GSSCaller调用者)被硬编码为返回 false 调用者是 HttpCaller 的实例。
对于其他类型的调用者,将检查javax.security.auth.useSubjectCredsOnly属性。