现在spring data cassandra是不能通过一个开关直接开启ssl的hostname verification的,也就是所谓的verify-full,所以得自己改下代码.
方案1:
implements CqlSessionBuilderCustomizer
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.cassandra.CassandraProperties;
import org.springframework.boot.autoconfigure.cassandra.CqlSessionBuilderCustomizer;
import org.springframework.stereotype.Component;
@Component
public class CqlSessionBuilderSSLCustomizer implements CqlSessionBuilderCustomizer {
@Autowired
CassandraProperties cassandraProperties;
@Override
public void customize(CqlSessionBuilder cqlSessionBuilder) {
if(cassandraProperties.isSsl()){
CustomSslEngineFactory customSslEngineFactory = new CustomSslEngineFactory("TLS");
cqlSessionBuilder.withSslEngineFactory(customSslEngineFactory);
}
}
}
方案2:
implements BeanPostProcessor
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.cassandra.CassandraProperties;
import org.springframework.stereotype.Component;
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Autowired
CassandraProperties cassandraProperties;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("cassandraSessionBuilder".endsWith(beanName)&&cassandraProperties.isSsl()){
CqlSessionBuilder cassandraSessionBuilder = (CqlSessionBuilder) bean;
CustomSslEngineFactory customSslEngineFactory = new CustomSslEngineFactory("TLS");
cassandraSessionBuilder.withSslEngineFactory(customSslEngineFactory);
}
return bean;
}
}
CustomSslEngineFactory 的代码
import com.datastax.oss.driver.api.core.metadata.EndPoint;
import com.datastax.oss.driver.api.core.ssl.SslEngineFactory;
import edu.umd.cs.findbugs.annotations.NonNull;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.TrustManagerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.KeyStore;
import java.security.SecureRandom;
public class CustomSslEngineFactory implements SslEngineFactory {
private final SSLContext sslContext;
private final String[] cipherSuites;
private final boolean requireHostnameValidation;
private final String TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore";
private final String TRUST_STORE_PASSWORD_PROPERTY = "javax.net.ssl.trustStorePassword";
private final String TRUST_STORE_TYPE_PROPERTY = "javax.net.ssl.trustStoreType";
private final String SSL_HOSTNAMEVERIFIER = "javax.net.ssl.hostnameverifier";
final String DEFAULT_TRUST_STORE = System.getProperty("java.home") + File.separator + "lib"
+ File.separator + "security" + File.separator + "cacerts";
private final String DEFAULT_TRUST_STORE_PASSWORD = "changeit";
public CustomSslEngineFactory(String encryptionMode){
try {
this.sslContext = buildContext(encryptionMode);
} catch (Exception e){
throw new IllegalStateException("Cannot initialize SSL Context",e);
}
this.cipherSuites = null;
String hostnameverifier = System.getProperty(SSL_HOSTNAMEVERIFIER);
if("false".equals(hostnameverifier)){
this.requireHostnameValidation = false;
}else {
this.requireHostnameValidation = true;
}
}
@NonNull
@Override
public SSLEngine newSslEngine(@NonNull EndPoint remoteEndpoint) {
SSLEngine engine;
SocketAddress remoteAddress = remoteEndpoint.resolve();
if (remoteAddress instanceof InetSocketAddress) {
InetSocketAddress socketAddress = (InetSocketAddress) remoteAddress;
engine = sslContext.createSSLEngine(socketAddress.getHostName(),socketAddress.getPort());
} else {
engine = sslContext.createSSLEngine();
}
engine.setUseClientMode(true);
if (cipherSuites != null) {
engine.setEnabledCipherSuites(cipherSuites);
}
if (requireHostnameValidation) {
SSLParameters parameters = engine.getSSLParameters();
parameters.setEndpointIdentificationAlgorithm("HTTPS");
engine.setSSLParameters(parameters);
}
return engine;
}
protected SSLContext buildContext(String encryptionMode) throws Exception {
String trustStore = System.getProperty(TRUST_STORE_PROPERTY);
String trustStorePassword = System.getProperty(TRUST_STORE_PASSWORD_PROPERTY);
if (null == trustStore || "".equals(trustStore)) {
trustStore = DEFAULT_TRUST_STORE;
}
if (null == trustStorePassword || "".equals(trustStorePassword)) {
trustStorePassword = DEFAULT_TRUST_STORE_PASSWORD;
}
String storePropType = System.getProperty(TRUST_STORE_TYPE_PROPERTY,
KeyStore.getDefaultType());
KeyStore ks = KeyStore.getInstance(storePropType);
InputStream trustStoreStream = new FileInputStream(trustStore);
ks.load(trustStoreStream, trustStorePassword.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
SSLContext sslContext = SSLContext.getInstance(encryptionMode.trim().toUpperCase());
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
return sslContext;
}
@Override
public void close() throws Exception {
// noting to do
}
}