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
错误。
之后,一切正常。
这种方法有重要的缺点,你应该知道。
-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