A dynamic SSL configuration has been created on IBM WebSphere that embeds a certificate in outgoing requests, you do not need to specify the paths to jks in the code. How can I configure sending a rest request so that HttpClient does not search for certificates in IBM jdk if the request comes via https?
CloseableHttpClient httpClient = null;
HttpClientBuilder builder = HttpClientBuilder
.create()
.useSystemProperties();
httpClient = builder.build();
HttpPost request = new HttpPost("https://test.org:8081/add");
// add request headers
request.addHeader("custom-key", "rev");
request.addHeader(HttpHeaders.USER_AGENT, "lebot");
CloseableHttpResponse response = httpClient.execute(request);
I have a running code that i am already using to connect to a server using SSL. The API i am using is commons-httpclient-3.1.jar and i cant not upgrade the jar.
The servers have upgraded to only use TSL 1.2.
Now my existing code is not working.
My current code is
HttpClient httpClient = new HttpClient();
PostMethod post = new PostMethod("https://XYZserver");
post.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_1);
File f = new File("C://sampleXml.xml");
RequestEntity entity = new FileRequestEntity(f, "Application/xml");
post.setRequestEntity(entity);
int statusCode = httpClient.executeMethod(post);
If i modify my code as per link How to force Commons HTTPClient 3.1 to use TLS 1.2 only for HTTPS? then my code is working fine.
I have few questions (As i was unable to find their answers?)
Why do we require a separate class CustomHttpsSocketFactory. Is it possible to modify existing code to use TLS
Is there any other way to do?
I have developed a Java Applet that works properly in a standard environment (no proxies). On the contrary if the applet is running on a client located behind a proxy, it correctly downloads files and accedes resources with simple http GET methods (java.net) but http POST method using Apache httpclient doesn't work.
I'm using:
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
clientBuilder.useSystemProperties();
CloseableHttpClient httpclient = clientBuilder.build();
to retrieve credentials for proxy authentication (these credentials have been already used by JVM, because I can accede external resources using java.net).
The execution of the POST method results in a 407 error (Proxy authentication required). Why useSystemProperties() can't retrieve the credentials for authentication? How can I retrieve username and passoword for the proxy?
I'm sending an https POST on some url using Apache HttpClient.
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);
And I get:
javax.net.ssl.SSLException: hostname in certificate didn't match: <*.*.*.*> != <*.url
Now after searching, I found the solution on stackoverflow:
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
HttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
And the POST is succesfully done.
But I don't understand what's happening here! Is my connection still secure?
Is this the right solution? If not, what's the best solution?
If you're not verifying the host name, you're simply not checking that you're talking to the entity you intended to talk to: it could be a MITM instead. It's the same issue as disabling VERIFYHOST with Curl, for example. You may also be interested in this question on Security.SE.
Regarding your initial problem, the host name (or IP address) in the certificate needs to match the host name you intended to contact, that is, the one in the URL.
If you're using an IP address, that IP address needs to be in the Subject Alternative Name of the certificate. (See this question.)
In general, it's easier to use names rather than IP addresses, even on a LAN.
EDIT: Considering you're using Apache Http Client 4.0.2, the release notes for 4.0.3 say:
This is an emergency release fixing a critical regression in the SSL
connection management code. HttpClient 4.0.2 release included an
improved support for multihome hosts, which unfortunately had a bug
causing the default SSL hostname verification logic to fail. An
attempt to establish an SSL connection with HttpClient 4.0.2 can
result in javax.net.ssl.SSLException: "hostname in certificate didn't
match ..." error.
Important - if you are allowing all hosts (that is, disabling host name verification), then it is certainly NOT safe. You shouldn't be doing this in production.
I think you are probably using self-signed certificates which may be the root cause of this exception. If yes, create a certificate with host as localhost (or your IP) and then try. On production, just enable host name verification and your code would run fine.
I need to set up proxy authentication against a SOCKS proxy.
I found out this post giving instructions that appear to work with common HTTP proxies.
httpclient.getHostConfiguration().setProxy("proxyserver.example.com", 8080);
HttpState state = new HttpState();
state.setProxyCredentials(new AuthScope("proxyserver.example.com", 8080),
new UsernamePasswordCredentials("username", "password"));
httpclient.setState(state);
Would that work with SOCKS proxies as well or do I have to do something different?
Java supports Socks proxy configuration via preferences:
socksProxyHost for the host name of the SOCKS proxy server
socksProxyPort for the port number, the default value being 1080
e.g.
java -DsocksProxyHost=socks.mydomain.com
(edit) For your example, if the socks proxy was configured in the way outlined before:
httpclient.getHostConfiguration().setProxy("proxyserver.example.com", 8080);
Credentials cred = new UsernamePasswordCredentials("username","password");
httpclient.getState().setProxyCredentials(AuthScope.ANY, cred);
You can also use this variant (without httpclient):
SocketAddress addr = new
InetSocketAddress("webcache.mydomain.com", 8080);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, addr); // Type.HTTP for HTTP
So completing the previous example, we can now add:
URL url = new URL("http://java.sun.com/");
URConnection conn = url.openConnection(proxy);
HTH
The Features page of Apache HTTPClient says:
Transparent connections through SOCKS proxies (version 4 & 5) using native Java socket support.
With "transparent", I guess they mean that it works without you needing to do anything special. Do you have a SOCKS proxy available somewhere? Can't you just try it out to see if it works?
SOCKS is not supported by HttpClient 3 natively. You can try the SOCKS support in JDK as suggested by others. The side effect is that your whole JVM will go through the same SOCKS proxy.
Java 5 supports Username/Password authentication in SOCKS (type 2). All you have to do is to setup the authenticator like this,
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
});
Again, this may not work for you because it affects all authentication in your JVM (HTTP auth, Proxy Auth).
You can provide a custom socket factory which implements the SOCKS protocol, and register it as your default HTTP protocol handler. This solution has a limitation similar to tuergeist's answer above has - it applies globally, to any HTTP connection you'll establish through HttpClient.
If you find this a problem, take a look at this correspondence, where Oleg suggests using HttpClient 4.0, but also refers to a possible patch in HostConfiguration class for HttpClient 3.x.
Another possible solution, which is my personal favorite, is to write a wrapper HTTP proxy to the socks proxy.
I tried
System.setProperty("socksProxyHost", "socks.xyz.com");
System.setProperty("socksProxyPort", "1000");
and it's working fine.