Authenticated HTTP proxy with Java

(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", "");

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).


You're almost there, you just have to append:

-Dhttp.proxyUser=someUserName
-Dhttp.proxyPassword=somePassword

Tags:

Java

Http

Proxy