Springboot关闭redis SSL证书校验

redis开启了TLS/SSL后, Springboot项目需要进行修改, 可以配置证书进行校验, 也可以直接关闭校验,。直接关闭校验比较简单,配置文件也不需要修改

一、配置证书进行校验

package com.shensu.jmb.config;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.util.Pool;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

/**
 * SSL的JedisConnectionFactory
 * @author ZXZ
 *
 */
@Configuration
public class SSLJedisConnectionFactory extends JedisConnectionFactory{

	/**
	 * 重写createRedisPool方法,让其使用SslSocketFactory创建连接池
	 */
	protected Pool<Jedis> createRedisPool() {
		SSLSocketFactory socketFactory = null;
		try {
			// redis服务器上开启TLS后的证书和密码(txt后缀)
			socketFactory = getSocketFactory("ca.crt", "redis.crt", "redis.key", "AC340A99205FA978");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return new JedisPool(super.getPoolConfig(),
				  "192.168.10.168",
				  7000,
				  1000,
				  "redis7_app",
				  true,
				  socketFactory,null,null);
	}

	/**
	 * 创建 SSLSocketFactory 工厂
	 *
	 * @param caCrtFile 服务端 CA 证书
	 * @param crtFile 客户端 CRT 文件
	 * @param keyFile 客户端 Key 文件
	 * @param password SSL 密码,随机
	 * @return {@link SSLSocketFactory}
	 * @throws Exception 异常
	 */
	public static SSLSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile, final String password) throws Exception {
		InputStream caInputStream = null;
		InputStream crtInputStream = null;
		InputStream keyInputStream = null;
		try {
			Security.addProvider(new BouncyCastleProvider());
			CertificateFactory cf = CertificateFactory.getInstance("X.509");
			// load CA certificate
			caInputStream = new ClassPathResource(caCrtFile).getInputStream();
			X509Certificate caCert = null;
			while (caInputStream.available() > 0) {
				caCert = (X509Certificate) cf.generateCertificate(caInputStream);
			}
			// load client certificate
			crtInputStream = new ClassPathResource(crtFile).getInputStream();
			X509Certificate cert = null;
			while (crtInputStream.available() > 0) {
				cert = (X509Certificate) cf.generateCertificate(crtInputStream);
			}

			// load client private key
			keyInputStream = new ClassPathResource(keyFile).getInputStream();
			PEMParser pemParser = new PEMParser(new InputStreamReader(keyInputStream));
			Object object = pemParser.readObject();
			PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
			JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
			KeyPair key;
			if (object instanceof PEMEncryptedKeyPair) {
				System.out.println("Encrypted key - we will use provided password");
				key = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
			} else {
				System.out.println("Unencrypted key - no password needed");
				key = converter.getKeyPair((PEMKeyPair) object);
			}
			pemParser.close();

			// CA certificate is used to authenticate server
			KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
			caKs.load(null, null);
			caKs.setCertificateEntry("ca-certificate", caCert);
			TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
			tmf.init(caKs);

			// client key and certificates are sent to server so it can authenticate
			// us
			KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
			ks.load(null, null);
			ks.setCertificateEntry("certificate", cert);
			ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{cert});
			KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
			kmf.init(ks, password.toCharArray());

			// finally, create SSL socket factory
			SSLContext context = SSLContext.getInstance("TLSv1.2");
			context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

			return context.getSocketFactory();

		}
		finally {
			if (null != caInputStream) {
				caInputStream.close();
			}
			if (null != crtInputStream) {
				crtInputStream.close();
			}
			if (null != keyInputStream) {
				keyInputStream.close();
			}
		}
	}
}

二、关闭证书校验

@Configuration(proxyBeanMethods = false)
public class RedisSSLConfiguration implements LettuceClientConfigurationBuilderCustomizer {

	@Override
	public void customize(LettuceClientConfigurationBuilder clientConfigurationBuilder) {
		// 关闭ssl证书校验
		clientConfigurationBuilder.useSsl().disablePeerVerification();
	}
}
关闭证书校验源码分析
// 找到redis配置入口
org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration#redisConnectionFactory

@Bean
@ConditionalOnMissingBean(RedisConnectionFactory.class)
LettuceConnectionFactory redisConnectionFactory(
      ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
      ClientResources clientResources) {
   // 获取配置信息, 连接属性ip,端口,数据库,密码都在 protected final RedisProperties getProperties() 方法里面
   LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(builderCustomizers, clientResources,
         getProperties().getLettuce().getPool());
   // 创建连接工厂
   return createLettuceConnectionFactory(clientConfig);
}


private LettuceClientConfiguration getLettuceClientConfiguration(
      ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
      ClientResources clientResources, Pool pool) {
   LettuceClientConfigurationBuilder builder = createBuilder(pool);
   // 设置clientName, shutdownTimeout
   applyProperties(builder);
   // url是空的
   if (StringUtils.hasText(getProperties().getUrl())) {
      customizeConfigurationFromUrl(builder);
   }
   builder.clientOptions(createClientOptions());
   builder.clientResources(clientResources);
   // builderCustomizers所属的接口ObjectProvider继承了Iterable接口,支持stream流,可以视它为一个集合
   // 如果我们实现了接口LettuceClientConfigurationBuilderCustomizer并注册为bean, 那么springboot启动时会扫描到它并添加到ObjectProvider中,这样下面的forEach就有数据, 会执行方法体里面的customize()方法;
   // 如果没有实现接口LettuceClientConfigurationBuilderCustomizer, forEach()就是空循环。
   // 在LettuceClientConfigurationBuilderCustomizer实现类的customize()里面, 我们可以设置不对ssl证书进行校验;
   // 如果接口LettuceClientConfigurationBuilderCustomizer有多个实现类, 会依次执行它们的customize()实现方法
   // ObjectProvider作用:如果注入实例为空时,使用ObjectProvider则避免了强依赖导致的依赖对象不存在异常;
   builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
   return builder.build();
}

参考

https://blog.csdn.net/Exception_sir/article/details/122047071
https://lettuce.io/core/release/reference/index.html#ssl.hostpeer-verification

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringbootRedis是常见的企业级开发系统中使用的技术。Springboot是一个用于快速开发基于Java的应用程序的框架,它简化了配置和部署的过程,提供了很多开箱即用的功能和扩展性。而Redis则是一种高性能的键值存储数据库,它支持各种数据结构和功能,如缓存、消息队列和分布式锁等。 在使用SpringbootRedis开发企业级系统时,可以利用Redis作为缓存来提高系统的性能和响应速度。通过将频繁访问的数据存储在Redis中,可以减少对数据库的访问次数,从而减轻数据库的负载。同时,Redis还提供了一些特有的功能,如发布/订阅机制和事务支持,可以帮助实现系统中的一些复杂业务逻辑。 在项目中集成SpringbootRedis可以通过引入相关的依赖和配置文件来实现。在pom.xml文件中添加相关的依赖,如spring-boot-starter-data-redis和jedis等,然后在application.properties或application.yml文件中配置Redis的连接信息和其他相关配置。 在Springboot中使用Redis可以通过注入RedisTemplate或StringRedisTemplate来进行操作。RedisTemplate提供了更丰富的操作接口,可以直接对各种类型的数据进行读写操作。而StringRedisTemplate则更加简化,主要用于对字符串类型的数据进行操作。 总而言之,SpringbootRedis的结合可以为企业级开发系统带来很多好处,包括提高系统性能、简化开发过程和实现一些复杂的业务逻辑。通过合理使用这两个技术,可以构建出高效、稳定和可扩展的企业级应用系统。<span class="em">1</span> #### 引用[.reference_title] - *1* [Java企业报表管理系统源码](https://download.csdn.net/download/m0_55416028/88269629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值