From f5f5808844560c9ca5b839c385bfc6e8ce6bea25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnaud=20Cogolu=C3=A8gnes?= Date: Tue, 11 Sep 2018 14:19:24 +0200 Subject: [PATCH] Document hostname verification for Java client References rabbitmq/rabbitmq-java-client#394 --- site/api-guide.xml | 2 +- site/ssl.xml | 56 ++++++++++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/site/api-guide.xml b/site/api-guide.xml index 872bcccc52..a0c2c49a17 100644 --- a/site/api-guide.xml +++ b/site/api-guide.xml @@ -1698,7 +1698,7 @@ factory.useSslProtocol(); To learn more about TLS support in RabbitMQ, see the TLS guide. If you only want to configure the Java client (especially the peer verification and trust manager parts), - read the appropriate section of the TLS guide. + read the appropriate section of the TLS guide.

diff --git a/site/ssl.xml b/site/ssl.xml index 4cb642d21f..f9da68ccb1 100644 --- a/site/ssl.xml +++ b/site/ssl.xml @@ -722,14 +722,11 @@ ssl_options.fail_if_no_peer_cert = false import java.io.*; import java.security.*; - import com.rabbitmq.client.*; -public class Example1 -{ - public static void main(String[] args) throws Exception - { +public class Example1 { + public static void main(String[] args) throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5671); @@ -745,16 +742,14 @@ public class Example1 channel.queueDeclare("rabbitmq-java-test", false, true, true, null); channel.basicPublish("", "rabbitmq-java-test", null, "Hello, World".getBytes()); - GetResponse chResponse = channel.basicGet("rabbitmq-java-test", false); - if(chResponse == null) { + if (chResponse == null) { System.out.println("No message retrieved"); } else { byte[] body = chResponse.getBody(); - System.out.println("Recieved: " + new String(body)); + System.out.println("Received: " + new String(body)); } - channel.close(); conn.close(); } @@ -806,12 +801,9 @@ import javax.net.ssl.*; import com.rabbitmq.client.*; +public class Example2 { -public class Example2 -{ - public static void main(String[] args) throws Exception - { - + public static void main(String[] args) throws Exception { char[] keyPassphrase = "MySecretPassword".toCharArray(); KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(new FileInputStream("/path/to/client_key.p12"), keyPassphrase); @@ -826,13 +818,14 @@ public class Example2 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(tks); - SSLContext c = SSLContext.getInstance("TLSv1.1"); + SSLContext c = SSLContext.getInstance("TLSv1.2"); c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5671); factory.useSslProtocol(c); + factory.enableHostnameVerification(); Connection conn = factory.newConnection(); Channel channel = conn.createChannel(); @@ -840,16 +833,14 @@ public class Example2 channel.queueDeclare("rabbitmq-java-test", false, true, true, null); channel.basicpublish("", "rabbitmq-java-test", null, "Hello, World".getBytes()); - GetResponse chResponse = channel.basicGet("rabbitmq-java-test", false); - if(chResponse == null) { + if (chResponse == null) { System.out.println("No message retrieved"); } else { byte[] body = chResponse.getBody(); - System.out.println("Recieved: " + new String(body)); + System.out.println("Received: " + new String(body)); } - channel.close(); conn.close(); } @@ -861,6 +852,33 @@ public class Example2 a RabbitMQ node with a certificate that has not been imported into the key store and watch the connection fail.

+ +

+ Note hostname verification must be explicitly enabled with + ConnectionFactory#enableHostnameVerification(). This checks + that the server certificate has been issued for the hostname the + client is requested. If you're using Java 6, you need to add + the Commons HttpClient dependency to your project, e.g. for Maven + and Gradle: +

+
+<!-- Maven dependency to add for hostname verification on Java 6 -->
+<dependency>
+    <groupId>org.apache.httpcomponents</groupId>
+    <artifactId>httpclient</artifactId>
+    <version>4.5.6</version>
+</dependency>
+
+
+// Gradle dependency to add for hostname verification on Java 6
+compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.6'
+
+

If you don't want to use Commons HttpClient, use + ConnectionFactory#enableHostnameVerification(HostnameVerifier) + with the HostnameVerifier instance of your choice. Again, this is + needed only for Java 6, hostname verification is built-in in Java 7 and more. +

+