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 kinit
command and got the credential cache" then the instance passed to Authenticator.setDefault()
"will be completely ignored".
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.
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.
Is there a way to override the documented behavior, i.e., is there a way to ignore the credentials stored by 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?
I've looked for the same thing you are asking. So far, I haven't found a way on the JDK to do that.
There is a request for enhancement on Java Bug Database. Take a look at the report to find out if that gets a response from Sun (vote up the report so that hopefully that gets fixed soon).
What I ended up doing, was override
sun.net.www.protocol.http.NTLMAuthentication
class. By looking atsun.net.www.protocol.http.HttpURLAuthentication
, I found that the only thing you need to modify is the result of:That method has a hardcoded return value,
true
on Windows platforms andfalse
otherwise. This code is extracted from a JDK installed on Windows 7: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 ofHttpURLConnection
class:To get
NTLMAuthentication
source code, I used this Java decompiler. Opened rt.jar located on the JDK installation folder and copied the desired class code.Then, I simply changed
supportsTransparentAuth
to 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.To compile it, I just placed the java file under sun/net/www/protocol/http folder structure and run:
Then run my application using:
That will tell the JVM to load our implementation of
NTLMAuthentication
before the one in rt.jar. You have to be careful to don't miss any default class loading paths with-Xbootclasspath
, or there will beClassNotFound
errors.After that, everything worked just fine.
This approach has important drawbacks that you should be aware of.
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
Hope this helps.
At least in Java 7 there is a class called
sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback
that seems to help with this situation. Single sign-on is only invoked for "trusted" URLs.Here is the simplest implementation to turn it off (have this initialiser called prior to opening the HTTP connection):
I guess the default implementation is to trust everything :(
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?
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/users@cxf.apache.org/msg22897.html