是否可以禁用 Windows 上的 Java“单点登录”(使用来自“凭据管理器”的凭据)?

2022-09-03 14:39:39

Java SE 6 文档中的 Oracle 的“Http 身份验证”页面说,“如果您以域用户身份在 Windows 机器上运行,或者,您正在已经发出命令并获取凭据缓存的 Linux 或 Solaris 机器上运行”,则传递给 Authenticator.setDefault() 的实例“将被完全忽略”。kinit

这与我所观察到的一致:在Windows系统上设置HTTP或HTTPS连接以托管X始终从“Windows Vault”的“Windows Credentials”传递主机X的凭据,如我的Windows 7“Credential Manager”控制面板页面所示。

但是,在我的用例中,我不想使用Windows可能存储的任何凭据,而是始终希望使用我在代码中显式指定的凭据。

有没有办法覆盖记录的行为,即有没有办法忽略Windows存储的凭据?

更新:如果没有,有人可以把我指向Java SE 6源代码中的某个地方,在那里我可以看到存储的Windows凭据不能被忽略吗?


答案 1

至少在Java 7中,有一个名为sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback的类似乎有助于解决这种情况。仅对“受信任”URL 调用单一登录。

以下是关闭它的最简单实现(在打开HTTP连接之前调用此初始化器):

static {
    NTLMAuthenticationCallback.setNTLMAuthenticationCallback(new NTLMAuthenticationCallback()
    {
        @Override
        public boolean isTrustedSite(URL url)
        {
            return false;
        }
    });
}

我想默认的实现是信任一切:(


答案 2

我一直在寻找你问的同样的事情。到目前为止,我还没有在JDK上找到做到这一点的方法。

有人请求增强 Java Bug 数据库。看看这份报告,看看这是否得到了Sun的回应(对报告进行投票,希望很快得到解决)。

我最终做的是覆盖类。通过查看,我发现您唯一需要修改的是以下结果:sun.net.www.protocol.http.NTLMAuthenticationsun.net.www.protocol.http.HttpURLAuthentication

NTLMAuthentication.supportsTransparentAuth()

该方法在Windows平台和其他位置具有硬编码的返回值。此代码是从 Windows 7 上安装的 JDK 中提取的:truefalse

static boolean supportsTransparentAuth()
{
  return true;
}

该方法告诉的是默认情况下是否应使用Windows凭据。如果设置为 ,则不会调用您的自定义身份验证器代码。请参阅此类片段:trueHttpURLConnection

//Declared as a member variable of HttpURLConnection
private boolean tryTransparentNTLMServer = NTLMAuthentication.supportsTransparentAuth();

//Inside of getServerAuthentication method.
PasswordAuthentication a = null;
if (!tryTransparentNTLMServer) {
    //If set to false, this will call Authenticator.requestPasswordAuthentication().
    a = privilegedRequestPasswordAuthentication(url.getHost(), addr, port, url.getProtocol(), "", scheme, url, RequestorType.SERVER);
}

/* If we are not trying transparent authentication then 
* we need to have a PasswordAuthentication instance. For
* transparent authentication (Windows only) the username 
* and password will be picked up from the current logged 
* on users credentials.
*/
if (tryTransparentNTLMServer || (!tryTransparentNTLMServer && a != null)) {
    //If set to true or if Authenticator did not return any credentials, use Windows credentials.
    //NTLMAuthentication constructor, if receives a == null will fetch current looged user credentials.
    ret = new NTLMAuthentication(false, url1, a);
}

为了获取源代码,我使用了这个Java反编译器。打开 rt.jar位于 JDK 安装文件夹中,并复制了所需的类代码。NTLMAuthentication

然后,我只是简单地更改为返回false。但是,如果此方法首先检查系统属性,然后基于该属性返回 true 或 false,则非常可取。supportsTransparentAuth

为了编译它,我只是将java文件放在sun/net/www/protocol/http文件夹结构下并运行:

javac NTLMAuthentication.java

然后使用以下命令运行我的应用程序:

java -Xbootclasspath:"path/to/your/sun/net/www/protocol/http/classes;normal/JDK/boot/directories"

这将告诉 JVM 在 rt.jar 中加载我们的实现。您必须小心不要错过任何带有 的默认类装入路径,否则会出现错误。NTLMAuthentication-XbootclasspathClassNotFound

在那之后,一切都很好。

这种方法具有您应该注意的重要缺点。

  • 存在安全风险。任何人都可以在您的启动文件夹中删除其他.class文件,并窃取用户凭据或其他重要信息。
  • 来自 Sun 包的代码可能会更改,恕不另行通知,因此与您的更改不兼容。
  • 如果部署此代码,则将违反 Sun 代码许可证。从文档中

-Xbootclasspath:bootclasspath 指定以分号分隔的目录、JAR 归档文件和 ZIP 归档文件列表以搜索引导类文件。它们用于代替 Java 2 SDK 中包含的引导类文件。注: 不应部署此选项以重写 rt.jar 中的类的应用程序,因为这样做会违反 Java 2 运行时环境二进制代码许可证。

因此,这绝对不适合生产环境。

最后,这是一个关于引导类路径选项和 Java 类装入器的优秀来源:PDF

希望这有帮助。


推荐