Authenticated HTTP proxy with Java
Solution 1
(EDIT: As pointed out by the OP, the using a java.net.Authenticator
is required too. I'm updating my answer accordingly for the sake of correctness.)
(EDIT#2: As pointed out in another answer, in JDK 8 it's required to remove basic
auth scheme from jdk.http.auth.tunneling.disabledSchemes
property)
For authentication, use java.net.Authenticator
to set proxy's configuration and set the system properties http.proxyUser
and http.proxyPassword
.
final String authUser = "user";
final String authPassword = "password";
Authenticator.setDefault(
new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(authUser, authPassword.toCharArray());
}
}
);
System.setProperty("http.proxyUser", authUser);
System.setProperty("http.proxyPassword", authPassword);
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
Solution 2
You're almost there, you just have to append:
-Dhttp.proxyUser=someUserName
-Dhttp.proxyPassword=somePassword
Solution 3
http://rolandtapken.de/blog/2012-04/java-process-httpproxyuser-and-httpproxypassword says:
Other suggest to use a custom default Authenticator. But that's dangerous because this would send your password to anybody who asks.
This is relevant if some http/https requests don't go through the proxy (which is quite possible depending on configuration). In that case, you would send your credentials directly to some http server, not to your proxy.
He suggests the following fix.
// Java ignores http.proxyUser. Here come's the workaround.
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
if (getRequestorType() == RequestorType.PROXY) {
String prot = getRequestingProtocol().toLowerCase();
String host = System.getProperty(prot + ".proxyHost", "");
String port = System.getProperty(prot + ".proxyPort", "80");
String user = System.getProperty(prot + ".proxyUser", "");
String password = System.getProperty(prot + ".proxyPassword", "");
if (getRequestingHost().equalsIgnoreCase(host)) {
if (Integer.parseInt(port) == getRequestingPort()) {
// Seems to be OK.
return new PasswordAuthentication(user, password.toCharArray());
}
}
}
return null;
}
});
I haven't tried it yet, but it looks good to me.
I modified the original version slightly to use equalsIgnoreCase() instead of equals(host.toLowerCase()) because of this: http://mattryall.net/blog/2009/02/the-infamous-turkish-locale-bug and I added "80" as the default value for port to avoid NumberFormatException in Integer.parseInt(port).
Solution 4
Most of the answer is in existing replies, but for me not quite. This is what works for me with java.net.HttpURLConnection (I have tested all the cases with JDK 7 and JDK 8). Note that you do not have to use the Authenticator class.
Case 1 : Proxy without user authentication, access HTTP resources
-Dhttp.proxyHost=myproxy -Dhttp.proxyPort=myport
Case 2 : Proxy with user authentication, access HTTP resources
-Dhttp.proxyHost=myproxy -Dhttp.proxyPort=myport -Dhttps.proxyUser=myuser -Dhttps.proxyPassword=mypass
Case 3 : Proxy without user authentication, access HTTPS resources (SSL)
-Dhttps.proxyHost=myproxy -Dhttps.proxyPort=myport
Case 4 : Proxy with user authentication, access HTTPS resources (SSL)
-Dhttps.proxyHost=myproxy -Dhttps.proxyPort=myport -Dhttps.proxyUser=myuser -Dhttps.proxyPassword=mypass
Case 5 : Proxy without user authentication, access both HTTP and HTTPS resources (SSL)
-Dhttp.proxyHost=myproxy -Dhttp.proxyPort=myport -Dhttps.proxyHost=myproxy -Dhttps.proxyPort=myport
Case 6 : Proxy with user authentication, access both HTTP and HTTPS resources (SSL)
-Dhttp.proxyHost=myproxy -Dhttp.proxyPort=myport -Dhttp.proxyUser=myuser -Dhttp.proxyPassword=mypass -Dhttps.proxyHost=myproxy -Dhttps.proxyPort=myport -Dhttps.proxyUser=myuser -Dhttps.proxyPassword=mypass
You can set the properties in the with System.setProperty("key", "value) too.
To access HTTPS resource you may have to trust the resource by downloading the server certificate and saving it in a trust store and then using that trust store. ie
System.setProperty("javax.net.ssl.trustStore", "c:/temp/cert-factory/my-cacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
Solution 5
For Java 1.8 and higher you must set
-Djdk.http.auth.tunneling.disabledSchemes=
to make proxies with Basic Authorization working with https along with Authenticator as mentioned in accepted answer
Andre Pastore
Computer Scientist Distributed Systems Architect & Engineer Software Engineer python, java, javascript, perl, bash, ... developer former-CTO Event Driven mindset Functional teams seeker Looking for diverse and multicultural leadership
Updated on February 17, 2020Comments
-
Andre Pastore about 4 years
How can I configure the username and password to authenticate a http proxy server using Java?
I just found the following configuration parameters:
http.proxyHost=<proxyAddress> http.proxyPort=<proxyPort> https.proxyHost=<proxyAddress> https.proxyPort=<proxyPort>
But, my proxy server requires authentication. How can I configure my app to use the proxy server?
-
divinedragon over 11 yearsI too got the response with the code snippet. But when I set the wrong values for password, if the request went through the proxy, it should say Connection refused. I got the output in that case as well. How can I verify if the requests are being sent via the proxy???
-
Carl Smotricz over 10 years@Pascal: I think you meant those last 2 lines to set
proxyHost
andproxyPort
, notproxyUser
andproxyPassword
, as the latter are already established by the Authenticator. Or am I missing something? -
user207421 about 10 years@divinedragon It shouldn't say 'connection refused'. It's not even possible. The connection was accepted by TCP, to the proxy, which then failed your authentication. At that point it is impossible for the proxy to generate a connection refusal.
-
Andreas Panagiotidis over 7 yearsYou do not have to add the Authenticator. For me, with Java 7 and Java 8 it enough to set the http.* properties.
-
Michael Paesold about 7 yearsI can confirm that using the Authenticator class is not required on JDK 7 or 8. Just use
-D<proto>.proxyUser=
and-D<proto>.proxyPassword=
. -
R. Karlus almost 7 yearsThe properties "http.proxyUser" and "http.proxyPassword" are not obligatory. You're specifying the Authenticator for the JVM. So, you can remove those configurations.
-
Stefan Haberl almost 5 yearsFor 2019 (JDK7+) this is the correct answer. The only thing missing to be totally complete is the no-proxy settings: To bypass your proxy for certain domains use
-Dhttp.nonProxyHosts=*.mydomain.com|localhost
. Note, that this setting is used for both HTTP and HTTPS. More info at the official documentation -
Lonzak almost 5 yearsAnd the schemes must be empty?
-
Youssef NAIT over 4 yearsIsn't it better to create the PasswordAuthentication outside of the anonymous class and return it in
getPasswordAuthentication
, this will prevent creating a new object each time the proxy authentication is required. -
jonenst about 4 yearsIt doesn't work on linux using oracle jdk 'ava version "1.8.0_231"' or "java version "11.0.5" 2019-10-15 LTS" Downvoted as I suppose that something else is happening during the reported working tests. (is it something windows specific?)
-
dimeros over 3 yearsCorrect, the basic authentication is introduced after java8_111 by default installation. In this case, the Authenticator is needed.
-
Hokkyokusei about 3 yearsMannn, this really saved my day. Thanks for posting this amazing answer. God Bless you.
-
res almost 2 yearsThis answer made me realize something obvious but that I wasn't seeing, nor was finding in other answers: http.proxyHost and https.proxyHost are different things!!! setting a "HTTP proxy" does not work with a "HTTPS URL call"