人们如何使Java SPNEGO客户端在Windows中工作



为了在Windows上使用Java进行客户端HTTP SPNEGO身份验证,您需要设置Windows注册表项allowtgtsessionkey。这是有据可查的。我不明白的是人们如何解决这个问题? 大多数公司网站永远不会接受为了单个软件而在 Windows 中更改此注册表项。还要考虑一下是否需要在组织中的每个工作站上更改这一点的麻烦。但这只是理论,因为到目前为止,我无法说服我们的任何客户更改此注册表项。

我不怪他们。大多数公司管理员会认为这是放松安全性,因此会反对它。

我读过这个:在 Java 或命令行实用程序中是否有办法使用本机 SSPI API 获取服务的 Kerberos 票证?

但它现在已经相当老了。

所以我真的,真的不明白人们如何让Windows + Java客户端+ Kerberos在大学环境,家庭用户等之外的任何东西上工作。

我从企业管理员那里得到的问题是"当IE和Firefox等应用程序在不设置此注册表项的情况下执行SPNEGO没有问题时,为什么我们需要设置此注册表项?好吧,我知道答案是什么。这是因为(最有可能)像IE和Firefox这样的应用程序是基于Windows原生的GSS API(SSPI),而Sun的Java使用自己的实现。

我假设使用像WAFFLE这样的东西可以解决问题,但我更喜欢纯Java解决方案。我还假设使用基于Java的解决方案(如Spring安全或Apache HttpClient)无济于事,因为它们都将遭受此问题的困扰。

任何帮助或指示将不胜感激。

UPDATE1

我发现在Oracle的错误数据库中有一个RFE。Oracle员工也就此事提交了补丁,JDK邮件列表中也讨论了此功能。这并没有让我变得更聪明,除了据我所知,这在当前的Java 7中不可用,甚至不是实验性的。右?

UPDATE2

这个问题现在再次出现在OpenJDK安全开发邮件列表中。

感谢您在

安全开发邮件列表中引用我的线程;-)我的中期目标是通过认可的类路径使这个补丁可用于Java 6+。您可能对我最近创建的这张华夫饼票感兴趣:https://github.com/dblock/waffle/issues/50

我也评估过华夫饼,但它不像Java-GSS,必须创建重复的代码,这是我想要避免的事情。

这整个问题并不完全是甲骨文的错。Microsoft只是通过 LSA CallPackage 函数阻止对会话票证的任何调用。借口是安全。我真的很想知道当我无法合理访问 TGT 时,SSPI 如何能够创建服务票证。因此,这样的闭源解决方案很糟糕。

目前,您只有三个选择:

  1. 通过Java手段再次获取TGT。
  2. 尝试华夫饼
  3. 编写自定义代码

我已经埋葬了蹩脚的注册表项,因为它无论如何都不适用于具有域帐户的本地管理员。就我而言,Windows上的Tomcat开发我在此期间求助于Java的kinit。

从Java 13开始,JDK中现在内置了Windows自己的GSS API(又名SSPI)的支持。

请参阅 Java 13 和 JDK-6722928 的发行说明。

更新:现在已将其向后移植到 Java 11。您需要使用 Java 11.0.10 或更高版本。如果您的 JDK 发行版在 bin 目录中包含名为 sspi_bridge.dll 的文件,则可以识别该发行版是否支持 SSPI。

甚至还有一张向后移植到 Java 8 的票证,但截至 2021 年 11 月,它尚未实现。

现在有一个

非常好的解决方案包含在Apache HTTP客户端中,使用JNA从本机SSPI API获取票证。看到这个答案:

https://stackoverflow.com/a/22865583/381161

对于寻找Java 8简单解决方案的人来说,Waffle是最佳选择。

法典:

import java.net.URI;
import java.util.Base64;
import waffle.windows.auth.IWindowsSecurityContext;
import waffle.windows.auth.impl.WindowsSecurityContextImpl;
public class KerberosCredentiels {
  /**
   * Generate current user token using Kerberos ticket
   */
  public String retrieveToken(URI uri) {
    IWindowsSecurityContext clientContext = WindowsSecurityContextImpl.getCurrent("Kerberos", convertToSPN(uri));
    byte[] token = clientContext.getToken();
    return Base64.getEncoder().encodeToString(token);
  }
  private static String convertToSPN(URI uri) {
    StringBuilder builder = new StringBuilder();
    builder.append("http/");
    builder.append(uri.getHost());
    return builder.toString();
  }
}

Maven 依赖项:

<dependency>
    <groupId>com.github.waffle</groupId>
    <artifactId>waffle-jna</artifactId>
    <version>1.8.3</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>4.3.0</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>4.3.0</version>
</dependency>

相关内容

  • 没有找到相关文章

最新更新