diff --git a/caf-caching/src/main/java/io/iec/edp/caf/caching/manager/RedisClientManager.java b/caf-caching/src/main/java/io/iec/edp/caf/caching/manager/RedisClientManager.java index 6cbb1c81dbf964180cf3ab715e97181ab73d34fa..7f787aac4dca3fde83bb02f97f3cfa5d5f0679a9 100644 --- a/caf-caching/src/main/java/io/iec/edp/caf/caching/manager/RedisClientManager.java +++ b/caf-caching/src/main/java/io/iec/edp/caf/caching/manager/RedisClientManager.java @@ -19,6 +19,7 @@ package io.iec.edp.caf.caching.manager; import io.iec.edp.caf.caching.properties.CacheSetting; import io.iec.edp.caf.caching.properties.JedisPoolConfigProperties; import io.iec.edp.caf.caching.properties.RedisCacheProperties; +import io.iec.edp.caf.caching.properties.SslSetting; import io.iec.edp.caf.caching.serializer.KeyStringSerializer; import io.iec.edp.caf.caching.enums.RedisServerMode; import org.springframework.data.redis.connection.RedisClusterConfiguration; @@ -33,6 +34,11 @@ import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import redis.clients.jedis.JedisPoolConfig; +import javax.net.ssl.*; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.*; +import java.security.cert.CertificateException; import java.time.Duration; import java.util.HashMap; import java.util.Map; @@ -49,14 +55,13 @@ public class RedisClientManager { private Map pools; private Lock lock; - private JedisClientConfiguration clientConfig; private static RedisSerializer defaultValueSerializer = new StringRedisSerializer(); private static KeyStringSerializer keyStringSerializer = new KeyStringSerializer(); private static GenericJackson2JsonRedisSerializer hashValueSerializer = new GenericJackson2JsonRedisSerializer(); /** - * 传入JedisPool相关配置 并构建clientConfig + * 传入JedisPool相关配置 并构建JedisPoolConfig * * @param jedisPoolConfigProperties */ @@ -71,13 +76,11 @@ public class RedisClientManager { poolConfig.setTestOnBorrow(jedisPoolConfigProperties.isTestOnBorrow()); poolConfig.setTestOnReturn(jedisPoolConfigProperties.isTestOnReturn()); poolConfig.setTestWhileIdle(jedisPoolConfigProperties.isTestWhileIdle()); - this.clientConfig = JedisClientConfiguration.builder() - .usePooling().poolConfig(poolConfig).and().readTimeout(Duration.ofMillis(jedisPoolConfigProperties.getMaxWaitMillis())).build(); - initRedisClients(settings, this.clientConfig); + initRedisClients(settings, poolConfig); } - private void initRedisClients(RedisCacheProperties settings, JedisClientConfiguration clientConfig) { + private void initRedisClients(RedisCacheProperties settings, JedisPoolConfig poolConfig) { if (settings != null && settings.getCacheSettings() != null) { for (CacheSetting cacheSetting : settings.getCacheSettings()) { String key = cacheSetting.getMode() == RedisServerMode.STANDALONE ? @@ -91,6 +94,15 @@ public class RedisClientManager { //读取配置并新建redisTemplate实例 RedisTemplate redisTemplate = new RedisTemplate(); JedisConnectionFactory jedisConnectionFactory = null; + JedisClientConfiguration.JedisClientConfigurationBuilder jedisClientConfigBuilder = JedisClientConfiguration.builder() + .usePooling().poolConfig(poolConfig) + .and() + .readTimeout(Duration.ofMillis(poolConfig.getMaxWaitMillis())); + + // TLS配置 + if (cacheSetting.getSsl().isEnable()) { + jedisClientConfigBuilder.useSsl().sslSocketFactory(createSslSocketFactory(cacheSetting.getSsl())); + } if (!this.pools.containsKey(key)) { switch (cacheSetting.getMode()) { @@ -101,9 +113,9 @@ public class RedisClientManager { redisSentinelConfiguration.setUsername(cacheSetting.getUsername()); redisSentinelConfiguration.setPassword(cacheSetting.getPassword()); // TODO: support setSentinelUsername(since spring-data-redis 2.7.0支持, 当前最新2.4.15; 2.5.11; 2.6.10均未支持) -// redisSentinelConfiguration.setSentinelUsername(cacheSetting.getSentinelUsername()); + // redisSentinelConfiguration.setSentinelUsername(cacheSetting.getSentinelUsername()); redisSentinelConfiguration.setSentinelPassword(cacheSetting.getSentinelPassword()); - jedisConnectionFactory = new JedisConnectionFactory(redisSentinelConfiguration, clientConfig); + jedisConnectionFactory = new JedisConnectionFactory(redisSentinelConfiguration, jedisClientConfigBuilder.build()); break; case CLUSTER: RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(); @@ -111,7 +123,7 @@ public class RedisClientManager { redisClusterConfiguration.setMaxRedirects(cacheSetting.getMaxRedirects()); redisClusterConfiguration.setUsername(cacheSetting.getUsername()); redisClusterConfiguration.setPassword(cacheSetting.getPassword()); - jedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration, clientConfig); + jedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration, jedisClientConfigBuilder.build()); break; case STANDALONE: RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); @@ -120,7 +132,7 @@ public class RedisClientManager { redisStandaloneConfiguration.setUsername(cacheSetting.getUsername()); redisStandaloneConfiguration.setPassword(cacheSetting.getPassword()); redisStandaloneConfiguration.setDatabase(cacheSetting.getDatabase()); - jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration, clientConfig); + jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfigBuilder.build()); break; } @@ -158,4 +170,52 @@ public class RedisClientManager { return this.pools.get(key); } + + /** + * 创建SslSocketFactory实例 + * @param sslSetting Ssl配置 + * @return SslSocketFactory + */ + private SSLSocketFactory createSslSocketFactory(SslSetting sslSetting) { + try { + // init SslContext + // init trustStore + TrustManager[] trustManagers = null; + if (sslSetting.getTrustStore() != null && !sslSetting.getTrustStore().isEmpty()) { + try (FileInputStream fis = new FileInputStream(sslSetting.getTrustStore())) { + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + KeyStore clientTrustStore = KeyStore.getInstance(sslSetting.getTrustStoreType()); + String trustPassword = sslSetting.getTrustStorePassword(); + + clientTrustStore.load(fis, trustPassword != null ? trustPassword.toCharArray() : null); + tmf.init(clientTrustStore); + trustManagers = tmf.getTrustManagers(); + } + } + + // init keyStore for 双向认证 + KeyManager[] keyManagers = null; + if (sslSetting.getKeyStore() != null && !sslSetting.getKeyStore().isEmpty()) { + try (FileInputStream fis = new FileInputStream(sslSetting.getKeyStore())) { + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + KeyStore keyTrustStore = KeyStore.getInstance(sslSetting.getKeyStoreType()); + String keyPassword = sslSetting.getKeyStorePassword(); + + keyTrustStore.load(fis, keyPassword != null ? keyPassword.toCharArray() : null); + kmf.init(keyTrustStore, keyPassword != null ? keyPassword.toCharArray() : null); + keyManagers = kmf.getKeyManagers(); + } + } + + // create SslContext + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagers, trustManagers, new SecureRandom()); + + return sslContext.getSocketFactory(); + } catch (NoSuchAlgorithmException | CertificateException | KeyStoreException | + IOException | UnrecoverableKeyException | KeyManagementException e) { + throw new RuntimeException("Failed to configure SSL/TLS", e); + } + } + } diff --git a/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/CacheSetting.java b/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/CacheSetting.java index 79d8fa090878bccbe4ef5ce7a9fb23200c5eafc1..089c64659ac6b525b7db33043c838fadf6f67435 100644 --- a/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/CacheSetting.java +++ b/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/CacheSetting.java @@ -96,4 +96,9 @@ public class CacheSetting { */ private int maxRedirects; + /** + * TLS配置 + */ + private SslSetting ssl = new SslSetting(); + } diff --git a/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/CacheSettingsData.java b/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/CacheSettingsData.java index 4bc57fbcfdf9b571cf51fb0de801a38d080d4a16..e418ec5f4e69cfa91e307e43ebeb654189c5bc06 100644 --- a/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/CacheSettingsData.java +++ b/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/CacheSettingsData.java @@ -95,4 +95,9 @@ public class CacheSettingsData { */ private int maxRedirects = 5; + /** + * TLS配置 + */ + private SslSetting ssl = new SslSetting(); + } diff --git a/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/RedisCacheProperties.java b/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/RedisCacheProperties.java index e685f9c14f1a3eaeb8548633d3da444806aa48d0..f90fa27e24b736149ef2418041046ee6a303f298 100644 --- a/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/RedisCacheProperties.java +++ b/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/RedisCacheProperties.java @@ -66,6 +66,7 @@ public class RedisCacheProperties { cacheSetting.setName(cacheSettingsData.getName()); cacheSetting.setUsername(cacheSettingsData.getUsername()); cacheSetting.setPassword(cacheSettingsData.getPassword()); + cacheSetting.setSsl(cacheSettingsData.getSsl()); switch (cacheSetting.getMode()) { case CLUSTER: cacheSetting.setClusterNodes(toNodeList(cacheSettingsData.getNodes())); diff --git a/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/SslSetting.java b/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/SslSetting.java new file mode 100644 index 0000000000000000000000000000000000000000..420f2e19e463743d12406e03063473fbc686a4c9 --- /dev/null +++ b/caf-caching/src/main/java/io/iec/edp/caf/caching/properties/SslSetting.java @@ -0,0 +1,34 @@ +package io.iec.edp.caf.caching.properties; + +import lombok.Data; + +/** + * TLS配置 + */ +@Data +public class SslSetting { + + // 是否开启tls + private boolean enable = false; + + // 信任库文件 + private String trustStore; + + // 信任库文件格式 + private String trustStoreType = "PKCS12"; + + // 信任库文件密码 + private String trustStorePassword; + + + // 双向认证 + // 密钥库文件 + private String keyStore; + + // 密钥库文件格式 + private String keyStoreType = "PKCS12"; + + // 密钥库文件密码 + private String keyStorePassword; + +} \ No newline at end of file diff --git a/caf-msu/caf-msu-client/pom.xml b/caf-msu/caf-msu-client/pom.xml deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000