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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6184881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:58:15  来源:igfitidea点击:

Can Java's 'single sign-on' (use credentials from 'Credential Manager') on Windows be disabled?

javawindowscredentialsauthenticator

提问by MarnixKlooster ReinstateMonica

Oracle's "Http Authentication"page from the Java SE 6 documentation says that "if you are running on a Windows machine as a domain user, or, you are running on a Linux or Solaris machine that has already issued the kinitcommand and got the credential cache" then the instance passed to Authenticator.setDefault()"will be completely ignored".

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

This matches what I observed: setting up an HTTP or HTTPS connection on a Windows system to host X always passes the credentials for host X from the 'Windows Credentials' of the 'Windows Vault', as seen in my Windows 7 'Credential Manager' Control Panel page.

这与我观察到的相符:在 Windows 系统上设置 HTTP 或 HTTPS 连接到主机 X 始终从“Windows Vault”的“Windows 凭据”传递主机 X 的凭据,如我的 Windows 7“凭据管理器”中所示控制面板页面。

However, in my use case I don't want to use any credentials which might be stored by Windows, but instead I always want to use credentials I explicitly specify in the code.

但是,在我的用例中,我不想使用任何可能由 Windows 存储的凭据,而是我总是想使用我在代码中明确指定的凭据。

Is there a way to override the documented behavior, i.e., is there a way to ignore the credentials stored by Windows?

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

Update:If not, could someone point me to a place in the Java SE 6 source code where I can see that the stored Windows credentials cannot be ignored?

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

采纳答案by jmend

I've looked for the same thing you are asking. So far, I haven't found a way on the JDK to do that.

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

There is a request for enhancement on Java Bug Database. Take a look at the reportto find out if that gets a response from Sun (vote up the report so that hopefully that gets fixed soon).

有对 Java Bug 数据库的增强请求。查看报告以了解 Sun 是否对此做出回应(对报告进行投票,希望该问题能尽快得到解决)。

What I ended up doing, was override sun.net.www.protocol.http.NTLMAuthenticationclass. By looking at sun.net.www.protocol.http.HttpURLAuthentication, I found that the only thing you need to modify is the result of:

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

NTLMAuthentication.supportsTransparentAuth()

That method has a hardcoded return value, trueon Windows platforms and falseotherwise. This code is extracted from a JDK installed on Windows 7:

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

static boolean supportsTransparentAuth()
{
  return true;
}

What that method tells is if Windows credentials should be used by default. If set to true, your custom Authenticator code won't be called. See this fragment of HttpURLConnectionclass:

该方法表明是否应默认使用 Windows 凭据。如果设置为true则不会调用您的自定义身份验证器代码。看到这个HttpURLConnection类的片段:

//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);
}

To get NTLMAuthenticationsource code, I used this Java decompiler. Opened rt.jar located on the JDK installation folder and copied the desired class code.

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

Then, I simply changed supportsTransparentAuthto return false. However, it would be highly desirable if this method checked first a system property and then return true or false based on that.

然后,我只是更改supportsTransparentAuth为返回 false。但是,如果此方法首先检查系统属性,然后根据它返回 true 或 false,那将是非常可取的。

To compile it, I just placed the java file under sun/net/www/protocol/http folder structure and run:

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

javac NTLMAuthentication.java

Then run my application using:

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

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

That will tell the JVM to load our implementation of NTLMAuthenticationbefore the one in rt.jar. You have to be careful to don't miss any default class loading paths with -Xbootclasspath, or there will be ClassNotFounderrors.

这将告诉 JVMNTLMAuthentication在 rt.jar 之前加载我们的实现。您必须小心不要错过任何带有 的默认类加载路径-Xbootclasspath,否则会出现ClassNotFound错误。

After that, everything worked just fine.

之后,一切正常。

This approach has important drawbacks that you should be aware of.

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

  • There are security risks. Anyone could drop a different .class file on your boot folder and steal the user credentials or other important information.
  • Code from Sun packages can change without notice and thus be incompatible with your changes.
  • If you deploy this code, you will be contravening the Sun code license. From the documentation:
  • 存在安全隐患。任何人都可以将不同的 .class 文件放在您的启动文件夹中,并窃取用户凭据或其他重要信息。
  • Sun 软件包中的代码可能会更改,恕不另行通知,因此与您的更改不兼容。
  • 如果您部署此代码,您将违反 Sun 代码许可。从文档

-Xbootclasspath:bootclasspath Specify a semicolon-separated list of directories, JAR archives, and ZIP archives to search for boot class files. These are used in place of the boot class files included in the Java 2 SDK. Note: Applications that use this option for the purpose of overriding a class in rt.jar should not be deployed as doing so would contravene the Java 2 Runtime Environment binary code license.

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

So, this is definitely not suitable for production environments.

所以,这绝对不适合生产环境。

Finally, this is an excellent source about boot class path option and Java class loaders: PDF

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

Hope this helps.

希望这可以帮助。

回答by Robin Power

At least in Java 7 there is a class called sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallbackthat seems to help with this situation. Single sign-on is only invoked for "trusted" URLs.

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

Here is the simplest implementation to turn it off (have this initialiser called prior to opening the HTTP connection):

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

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

I guess the default implementation is to trust everything :(

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

回答by avi

It seems that the class sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback was added to java 6.0 patch 24+ so the solution suggested can work in java 6.0 as well. See reference in the following post: http://www.mail-archive.com/[email protected]/msg22897.html

似乎类 sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback 已添加到 java 6.0 补丁 24+ 中,因此建议的解决方案也可以在 java 6.0 中使用。请参阅以下帖子中的参考:http: //www.mail-archive.com/[email protected]/msg22897.html

回答by matthema

With Java v8 212 or higher, "transparent" SSO authentication via NTLMv2?is disabled by default, as a consequence of this CVE: https://nvd.nist.gov/vuln/detail/CVE-2019-2426. For more information: How to provide ntlm authentication while calling any url?

对于 Java v8 212 或更高版本,默认情况下禁用通过 NTLMv2 进行的“透明”SSO 身份验证,这是 CVE 的结果:https: //nvd.nist.gov/vuln/detail/CVE-2019-2426。有关更多信息:如何在调用任何 url 时提供 ntlm 身份验证?