我们正在使用Apache HttpClient库来连接到Kerberos安全的REST端点,该端点位于为多个应用程序提供服务的负载均衡器后面,因此正向和反向DNS查找结果之间存在不匹配。
虽然我们可以通过在krb5.conf文件中设置rdns = false来使用cURL成功建立经过身份验证的会话,但在Java中似乎不可能 - 它只是忽略此设置并始终执行反向DNS查找,由于不匹配,当然会失败。
我没有找到关于这个问题的太多信息,但我确实找到了这个开放的Jira项目,它解释了我们看到的行为......但没有提供任何解决方法: https://bugs.openjdk.java.net/browse/JDK-8189361
到目前为止,我发现的唯一可行的解决方法是使用自定义名称服务提供程序“劫持”反向DNS查找并返回所需的主机名。
关于这方面也有非常稀少的信息,但我发现这个近12年前的博客文章似乎仍然有用(虽然感觉就像一个非常脏的黑客):
http://rkuzmik.blogspot.co.il/2006/08/local-managed-dns-java_11.html
然而,感觉我可能在这里遗漏了一些东西,因为似乎不太可能有关于这个问题的信息很少。
在Java中执行Kerberos时,还有其他人遇到过禁用反向DNS查找的问题吗?如果是这样,你是如何解决的。
答案 0 :(得分:3)
上周我使用VIP时遇到了同样的错误,但反向dns给了我物理服务器的FQDN。 不幸的是,我没有直接使用HttpClient-4.5.1库,而是在幕后使用它的软件;出于这个原因,我一直在寻找一个解决方案而不涉及该软件的源代码。 我确实做了大量的试验(jvm spi.dns,jvm gss native,dnsjava.jar,...),但遗憾的是没有任何成功。 最后,"脏解决方案"我一直在重建HttpClient jar来改变类" org.apache.http.impl.auth.GGSSchemeBase" on the method" String resolveCanonicalHostname(final String host)"。
对于一个可能的"好的解决方案",我看到这个类正在接收参数" boolean useCanonicalHostname"直接在它的构造函数中,如果您可以直接使用HttpClient库,可能有一种方法将此参数设置为false并将其传播到生成kerberos服务票证的此类(如果参数为false,则rdns检查未完成,而是使用主机字符串)。
我希望这个提示可以帮助你。
BR
Samuele
答案 1 :(得分:1)
对于使用Apache HttpClient库遇到同样问题的任何人,下面的代码都可以使用 - 重要的是SPNegoSchemeFactory的构造函数,它是:
public SPNegoSchemeFactory(final boolean stripPort, final boolean useCanonicalHostname)
以下是我现在使用的Scala代码:
private val registry = RegistryBuilder
.create()
.register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true,false))
.build()
.asInstanceOf[Lookup[AuthSchemeProvider]]
private val credentialsProvider = new BasicCredentialsProvider
private val useJaasCreds = new Credentials()
{
def getPassword: String = null
def getUserPrincipal: Principal = null
}
credentialsProvider.setCredentials(new AuthScope(null, -1, null), useJaasCreds)
private val httpClient = HttpClientBuilder
.create()
.setDefaultAuthSchemeRegistry(registry)
.setDefaultCredentialsProvider(credentialsProvider)
.build()
答案 2 :(得分:1)
我遇到了同样的问题,经过调查后发现,现有的 Java HTTP / Kerberos 客户端都无法完全控制生成 SPN 。所以我开始研究一个独立的库,它允许生成和验证WWW-Authenticate: Negotiate XXX
/ URL url = new URL("http://cname.provider.acme.com/api/operation1");
SpnegoContext context = spnegoClient.createContext("http://cname.provider.acme.com"); // Will result in HTTP/cname.provider.acme.com SPN
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", context.createTokenAsAuthroizationHeader());
HTTP 标题。
它被称为Kerb4J。
考虑您有一个域 cname.provider.acme.com ,它是域 a.provider.acme.com 的CNAME(AKA别名),其规范 DNS 名称(即在反向DNS查找后解析)是 ptr.provider.acme.com
您想使用您最喜欢的 HTTP 客户端向 cname.provider.acme.com 发出请求,但不希望它对进行任何其他操作 SPN 计算期间的DNS 。
URL url = new URL("http://localhost:8080/api/operation1");
SpnegoContext context = spnegoClient.createContext("http://cname.provider.acme.com"); // Will result in HTTP/cname.provider.acme.com SPN
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", context.createTokenAsAuthroizationHeader());
使用 Kerb4J ,您甚至可以使用任意 SPN 来制作 SPNEGO 保护的请求(在本地计算机上测试代码时很有用):< / p>
predict_on_batch(self, x)
Returns predictions for a single batch of samples.
Arguments
x: Input samples, as a Numpy array.
Returns
Numpy array(s) of predictions.
Maven Central中有一个已发布的版本。
免责声明:我是Kerb4J的作者。