- Java Proxy & SSL
- HTTP proxy in java
- JVM Proxy
- Proxy with authentication
- URLConnection
- java.net.Proxy
- SOAPConnection
- Apache
- CXF
- HttpClient
- Spring Rest Template
- JDK 8.111+
- SSL troubleshooting
- Configure HTTP/HTTPS Proxy Settings Java
- Use system Proxy Settings
- Using Command Line JVM Settings
- Passing arguments to Tomcat
- Catalina.properties
- Catalina.bat
- Programatically set HTTP Proxy Settings
- Authenticating Proxy
- References
Java Proxy & SSL
While security requirement increase in enterprises more and more Proxies will need special care. Let’s see up to date practices to manage them.
HTTP proxy in java
JVM Proxy
This will force the whole JVM to use proxy, including database access (unless excluded using nonProxyHosts)
System.setProperty("https.proxyHost", "172.27.0.254"); System.setProperty("https.proxyPort", "8080"); System.setProperty("https.nonProxyHosts", "localhost|127.*|[::1]");
-Dhttps.proxyHost=172.27.0.254 -Dhttps.proxyPort=8080 -Dhttp.nonProxyHosts="localhost|127.*|[::1]"
System.setProperty("http.proxyHost", "172.27.0.254"); System.setProperty("http.proxyPort", "8080"); System.setProperty("http.nonProxyHosts", "localhost|127.*|[::1]");
Can also be used from command line : -Dhttp.proxyHost=172.27.0.254 -Dhttp.proxyPort=8080
Proxy with authentication
When you receive a ‘407: Proxy Authentication Required’, you may need Proxy authentication :
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", "0"); String user = System.getProperty(prot + ".proxyUser", ""); String password = System.getProperty(prot + ".proxyPassword", ""); if (getRequestingHost().equalsIgnoreCase(host)) < if (Integer.parseInt(port) == getRequestingPort()) < return new PasswordAuthentication(user, password.toCharArray()); >> > return null; > >);
Once again this will impact the whole JVM and should be called once only.
System properties (proxyUser, proxyPassword) does not work :
@Test public void test_HttpURLConnection_setProperty_auth() throws IOException < // Required for JDK8.111+ System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); System.setProperty("jdk.http.auth.proxying.disabledSchemes", ""); // URL url = new URL("https://www.example.com"); // System.setProperty("https.proxyHost", "172.27.0.254"); System.setProperty("https.proxyPort", "8080"); System.setProperty("https.proxyUser", "user"); System.setProperty("https.proxyPassword", "pass"); // Could be used System.setProperty("http.proxyHost", "172.27.0.254"); System.setProperty("http.proxyPort", "8080"); System.setProperty("http.proxyUser", "user"); System.setProperty("http.proxyPassword", "pass"); // HttpURLConnection con = (HttpURLConnection) url.openConnection(); /** * As an evidence, http*.proxyUser does not work */ assertEquals(407, con.getResponseCode()); assertEquals("Proxy Authentication Required", con.getResponseMessage()); >
URLConnection
java.net.Proxy
When using URLConnection a better way is possible using java.net.Proxy (which does not force the whole JVM) :
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("172.27.0.254", 8080); URL url = new URL("https://www.example.com); HttpURLConnection con = (HttpURLConnection) url.openConnection(proxy);
This can be used with a default Authenticator.
SOAPConnection
You can create to own SOAP request without any framework using SOAPConnection
SOAPConnection soapConnection = SOAPConnectionFactory.newInstance().createConnection(); SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), "https://salesforce.com/services/Soap/u/41.0");
But the SOAPConnectionFactory returns a com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection which does not use java.net.Proxy :
private HttpURLConnection createConnection(URL endpoint) throws IOException
So you have to use System properties to specify a Proxy server (hence impacting all JVM or playing with exclusions).
Apache
CXF
CXF uses URLConnection for synchronous calls, and HttpClient for asynchrounous ones. Later may also be forced for synchronous calls.
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean(); jaxWsProxyFactoryBean.setAddress("https://endpoint.soap"); jaxWsProxyFactoryBean.setServiceClass(MyInterface.class); MyInterface myService = (MyInterface) jaxWsProxyFactoryBean.create(); Client client = ClientProxy.getClient(myService); HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); HTTPClientPolicy httpClientPolicy = httpConduit.getClient(); httpClientPolicy.setProxyServer("172.27.0.254"); httpClientPolicy.setProxyServerPort(8080); httpClientPolicy.setProxyServerType(ProxyServerType.HTTP); // If proxy Authentication : httpConduit.getProxyAuthorization().setUserName("user"); httpConduit.getProxyAuthorization().setPassword("passw");
HttpClient
HttpClient also uses HTTPConduit to configure your Proxy settings.
Spring Rest Template
private final RestTemplate getProxiedRestTemplate() < RestTemplate r = null; if (isProxyActivated()) < HttpClientBuilder client = HttpClientBuilder.create(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); client.setProxy(new HttpHost("172.27.0.254", 8080)); if (withAuthentication()) < Credentials credentials = new UsernamePasswordCredentials(getProxyUsername(), getProxyPassword()); AuthScope authScope = new AuthScope("172.27.0.254", 8080); CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials(authScope, credentials); client.setDefaultCredentialsProvider(credsProvider); >requestFactory.setHttpClient(client.build()); r = new RestTemplate(requestFactory); > else < r = new RestTemplate(); >return r; >
JDK 8.111+
Disable Basic authentication for HTTPS tunneling In some environments, certain authentication schemes may be undesirable when proxying HTTPS. Accordingly, the Basic authentication scheme has been deactivated, by default, in the Oracle Java Runtime, by adding Basic to the jdk.http.auth.tunneling.disabledSchemes networking property. Now, proxies requiring Basic authentication when setting up a tunnel for HTTPS will no longer succeed by default. If required, this authentication scheme can be reactivated by removing Basic from the jdk.http.auth.tunneling.disabledSchemes networking property, or by setting a system property of the same name to “” ( empty ) on the command line.
Additionally, the jdk.http.auth.tunneling.disabledSchemes and jdk.http.auth.proxying.disabledSchemes networking properties, and system properties of the same name, can be used to disable other authentication schemes that may be active when setting up a tunnel for HTTPS, or proxying plain HTTP, respectively. JDK-8160838 (not public)
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); System.setProperty("jdk.http.auth.proxying.disabledSchemes", "");
Or as a JVM parameter in your command line :
-Djdk.http.auth.tunneling.disabledSchemes="" -Djdk.http.auth.proxying.disabledSchemes=""
Example to start your jetty server :
JAVA_OPTIONS="$JAVA_OPTIONS -Djdk.http.auth.tunneling.disabledSchemes="" -Djdk.http.auth.proxying.disabledSchemes="" "
SSL troubleshooting
System.setProperty("javax.net.debug", "all");// "ssl:record:plaintext" sun.util.logging.PlatformLogger.getLogger("sun.net.www.protocol.http.HttpURLConnection").setLevel(sun.util.logging.PlatformLogger.Level.ALL); sun.util.logging.PlatformLogger.getLogger("sun.net.www.protocol.http.HttpsURLConnection").setLevel(sun.util.logging.PlatformLogger.Level.ALL);
Enable old insecure protocols :
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2,SSLv3");
Configure HTTP/HTTPS Proxy Settings Java
For local networks inside an organisation it is common to access the public internet through a HTTP Proxy. This tutorial will show you how you can globally set the HTTP Proxy Settings in Java.
Use system Proxy Settings
If you have a proxy configured on your local system. You can try to set the java.net.useSystemProxies (default is false) this property will try to apply the system properties.
This property is introduced since JDK 1.5. Note that this property is checked only once at startup.
-Djava.net.useSystemProxies=true System.setProperty("java.net.useSystemProxies", "true");
Using Command Line JVM Settings
You can configure your server to use a HTTP Proxy server with JVM command line arguments. You can pass the following arguments either when you use a http or https proxy server.
// HTTP -Dhttp.proxyHost=http://proxy.memorynotfound.com -Dhttp.proxyPort=80 // HTTPS -Dhttps.proxyHost=https://proxy.memorynotfound.com -Dhttps.proxyPort=443
Passing arguments to Tomcat
Catalina.properties
Append following properties to the catalina.properties file in Tomcat: $/conf/catalina.properties .
http.proxyHost=http://proxy.memorynotfound.com http.proxyPort=80
Catalina.bat
Append following properties to the startup file in Tomcat:
JAVA_OPTS="-Dhttp.proxyHost=http://proxy.memorynotfound.com -Dhttp.proxyPort=80"
Programatically set HTTP Proxy Settings
If you want you can also add proxy settings programmatically use the same properties but this time set them using System.setProperty(); .
// HTTP System.setProperty("http.proxyHost", "http://proxy.memorynotfound.com"); System.setProperty("http.proxyPort", "80"); System.setProperty("http.nonProxyHosts", "localhost|127.0.0.1"); // HTTPS System.setProperty("https.proxyHost", "https://proxy.memorynotfound.com"); System.setProperty("https.proxyPort", "443");
Authenticating Proxy
Taking the above into account. Here is how you can Authenticate via a proxy. This initialisation code is typically executed at application startup. So make sure you register this authenticator before you make any HTTP Requests that require Proxy Authentication.
// settings proxy credentials System.setProperty("http.proxyUser", "proxyUser"); System.setProperty("http.proxyPassword", "secret"); // 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()) < return new PasswordAuthentication(user, password.toCharArray()); >> > return null; > >);