Windows上的Java“单一login”(使用“Credential Manager”中的凭据)是否被禁用?

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

这符合我观察到的情况:在Windows系统上设置HTTP或HTTPS连接到主机X总是从“Windows Vault”的“Windows Credentials”传递主机X的凭据,如我的Windows 7“凭证pipe理器”控制面板页面。

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

有没有办法来覆盖logging的行为,即是否有办法忽略由Windows存储的凭据?

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

我一直在寻找你所要求的同样的东西。 到目前为止,我还没有在JDK上找到这样做的方法。

有一个Java Bug数据库增强的请求。 看看这个报告 ,看看是否得到了Sun的回应(把这个报告投给我们,希望能很快得到解决)。

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

 NTLMAuthentication.supportsTransparentAuth() 

该方法具有硬编码的返回值,在Windows平台上为false否则为false 此代码是从安装在Windows 7上的JDK中提取的:

 static boolean supportsTransparentAuth() { return true; } 

这种方法告诉的是,如果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); } 

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

然后,我只是改变了supportsTransparentAuth返回false。 但是,如果此方法首先检查一个系统属性,然后根据此属性返回true或false,则将非常可取。

为了编译它,我只是把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实现。 你必须小心,不要错过任何使用-Xbootclasspath默认类加载路径,否则会出现ClassNotFound错误。

之后,一切正常。

这种方法有重要的缺点,你应该知道。

  • 存在安全风险。 任何人都可以在引导文件夹中放置不同的.class文件,并窃取用户凭据或其他重要信息。
  • Sun软件包中的代码可能会更改,恕不另行通知,因此与您的更改不符。
  • 如果您部署此代码,您将违反Sun代码许可证。 从文档 :

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

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

最后,这是关于引导类路径选项和Java类加载器的极好源码: PDF

希望这可以帮助。

至少在Java 7中有一个名为sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback的类似乎有助于这种情况。 单一登录仅针对“可信”网址进行调用。

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

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

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

看来,类sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback被添加到Java 6.0补丁24 +所以解决方案建议可以在Java 6.0中工作。 请参阅以下文章中的参考资料: http : //www.mail-archive.com/users@cxf.apache.org/msg22897.html