1
1
/*
2
- * Copyright 2002-2017 the original author or authors.
2
+ * Copyright 2002-2018 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
16
16
17
17
package org .springframework .amqp .rabbit .connection ;
18
18
19
+ import java .lang .reflect .Method ;
19
20
import java .net .URI ;
20
21
import java .net .URISyntaxException ;
21
22
import java .security .KeyManagementException ;
22
23
import java .security .KeyStore ;
23
- import java .security .KeyStoreException ;
24
24
import java .security .NoSuchAlgorithmException ;
25
25
import java .security .SecureRandom ;
26
26
import java .util .Arrays ;
27
27
import java .util .Map ;
28
28
import java .util .Properties ;
29
29
import java .util .concurrent .ExecutorService ;
30
30
import java .util .concurrent .ThreadFactory ;
31
+ import java .util .concurrent .atomic .AtomicReference ;
31
32
32
33
import javax .net .SocketFactory ;
33
34
import javax .net .ssl .KeyManager ;
42
43
import org .springframework .beans .factory .config .AbstractFactoryBean ;
43
44
import org .springframework .core .io .Resource ;
44
45
import org .springframework .core .io .support .PathMatchingResourcePatternResolver ;
46
+ import org .springframework .util .Assert ;
47
+ import org .springframework .util .ReflectionUtils ;
48
+ import org .springframework .util .ReflectionUtils .MethodCallback ;
49
+ import org .springframework .util .ReflectionUtils .MethodFilter ;
45
50
import org .springframework .util .StringUtils ;
46
51
47
52
import com .rabbitmq .client .ConnectionFactory ;
56
61
* setter methods and optionally enabling SSL, with or without
57
62
* certificate validation. When {@link #setSslPropertiesLocation(Resource) sslPropertiesLocation}
58
63
* is not null, the default implementation loads a {@code PKCS12} keystore and a
59
- * {@code JKS} truststore using the supplied properties and intializes {@code SunX509} key
64
+ * {@code JKS} truststore using the supplied properties and initializes {@code SunX509} key
60
65
* and trust manager factories. These are then used to initialize an {@link SSLContext}
61
66
* using the {@link #setSslAlgorithm(String) sslAlgorithm} (default TLSv1.1).
62
67
* <p>
75
80
*/
76
81
public class RabbitConnectionFactoryBean extends AbstractFactoryBean <ConnectionFactory > {
77
82
83
+ private static final Method enableHostnameVerificationNoArgMethod ;
84
+
85
+ static {
86
+ final AtomicReference <Method > method1 = new AtomicReference <>();
87
+ ReflectionUtils .doWithMethods (ConnectionFactory .class , m -> {
88
+ if (m .getParameterTypes ().length == 0 ) {
89
+ method1 .set (m );
90
+ }
91
+ }, m -> m .getName ().equals ("enableHostnameVerification" ));
92
+
93
+ enableHostnameVerificationNoArgMethod = method1 .get ();
94
+ }
95
+
78
96
private final Log logger = LogFactory .getLog (getClass ());
79
97
80
98
private static final String KEY_STORE = "keyStore" ;
@@ -103,30 +121,32 @@ public class RabbitConnectionFactoryBean extends AbstractFactoryBean<ConnectionF
103
121
104
122
private Resource sslPropertiesLocation ;
105
123
106
- private volatile String keyStore ;
124
+ private String keyStore ;
107
125
108
- private volatile String trustStore ;
126
+ private String trustStore ;
109
127
110
- private volatile Resource keyStoreResource ;
128
+ private Resource keyStoreResource ;
111
129
112
- private volatile Resource trustStoreResource ;
130
+ private Resource trustStoreResource ;
113
131
114
- private volatile String keyStorePassphrase ;
132
+ private String keyStorePassphrase ;
115
133
116
- private volatile String trustStorePassphrase ;
134
+ private String trustStorePassphrase ;
117
135
118
- private volatile String keyStoreType ;
136
+ private String keyStoreType ;
119
137
120
- private volatile String trustStoreType ;
138
+ private String trustStoreType ;
121
139
122
- private volatile String sslAlgorithm = TLS_V1_1 ;
140
+ private String sslAlgorithm = TLS_V1_1 ;
123
141
124
- private volatile boolean sslAlgorithmSet ;
142
+ private boolean sslAlgorithmSet ;
125
143
126
- private volatile SecureRandom secureRandom ;
144
+ private SecureRandom secureRandom ;
127
145
128
146
private boolean skipServerCertificateValidation ;
129
147
148
+ private boolean enableHostnameVerification ;
149
+
130
150
public RabbitConnectionFactoryBean () {
131
151
this .connectionFactory .setAutomaticRecoveryEnabled (false );
132
152
}
@@ -604,6 +624,21 @@ public void setChannelRpcTimeout(int channelRpcTimeout) {
604
624
this .connectionFactory .setChannelRpcTimeout (channelRpcTimeout );
605
625
}
606
626
627
+ /**
628
+ * Enable server hostname verification for TLS connections.
629
+ * <p>
630
+ * This enables hostname verification regardless of the IO mode used (blocking or
631
+ * non-blocking IO).
632
+ * Requires amqp-client 5.4.0 or later.
633
+ * @param enable true to enable.
634
+ * @since 1.7.10
635
+ */
636
+ public void setEnableHostnameVerification (boolean enable ) {
637
+ Assert .notNull (enableHostnameVerificationNoArgMethod ,
638
+ "Host name verification requires amqp-client 5.4.0 or later" );
639
+ this .enableHostnameVerification = enable ;
640
+ }
641
+
607
642
@ Override
608
643
public Class <?> getObjectType () {
609
644
return ConnectionFactory .class ;
@@ -686,6 +721,7 @@ protected void setUpSSL() throws Exception {
686
721
SSLContext context = createSSLContext ();
687
722
context .init (keyManagers , trustManagers , this .secureRandom );
688
723
this .connectionFactory .useSslProtocol (context );
724
+ checkHostVerification ();
689
725
}
690
726
}
691
727
@@ -701,14 +737,20 @@ protected SSLContext createSSLContext() throws NoSuchAlgorithmException {
701
737
}
702
738
703
739
704
- private void useDefaultTrustStoreMechanism ()
705
- throws NoSuchAlgorithmException , KeyManagementException , KeyStoreException {
740
+ private void useDefaultTrustStoreMechanism () throws Exception {
706
741
SSLContext sslContext = SSLContext .getInstance (this .sslAlgorithm );
707
742
TrustManagerFactory trustManagerFactory =
708
743
TrustManagerFactory .getInstance (TrustManagerFactory .getDefaultAlgorithm ());
709
744
trustManagerFactory .init ((KeyStore ) null );
710
745
sslContext .init (null , trustManagerFactory .getTrustManagers (), null );
711
746
this .connectionFactory .useSslProtocol (sslContext );
747
+ checkHostVerification ();
748
+ }
749
+
750
+ private void checkHostVerification () throws Exception {
751
+ if (this .enableHostnameVerification ) {
752
+ enableHostnameVerificationNoArgMethod .invoke (this .connectionFactory );
753
+ }
712
754
}
713
755
714
756
}
0 commit comments