From 77e6759d9a3d87b26d81694b10459b9edd199c25 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 2 Dec 2020 04:01:59 +0800 Subject: [PATCH] add SSLUtil --- CHANGELOG.md | 1 + .../cn/hutool/core/net/SSLContextBuilder.java | 146 ++++++++++++++++++ .../main/java/cn/hutool/core/net/SSLUtil.java | 49 ++++++ .../http/ssl/SSLSocketFactoryBuilder.java | 127 ++++++++------- 4 files changed, 264 insertions(+), 59 deletions(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/net/SSLContextBuilder.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/net/SSLUtil.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a26bfb76..f33b0a485 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ * 【core 】 增加PunyCode(issue#1268@Gitee) * 【core 】 ArrayUtil增加isSorted方法(pr#1271@Github) * 【captcha】 增加GifCaptcha(pr#1273@Github) +* 【core 】 增加SSLUtil、SSLContextBuilder ### Bug修复 * 【cron 】 修复CronTimer可能死循环的问题(issue#1224@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/SSLContextBuilder.java b/hutool-core/src/main/java/cn/hutool/core/net/SSLContextBuilder.java new file mode 100644 index 000000000..776142391 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/net/SSLContextBuilder.java @@ -0,0 +1,146 @@ +package cn.hutool.core.net; + +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import java.security.GeneralSecurityException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +/** + * {@link SSLContext}构建器 + * + * @author Looly + * @since 5.5.2 + */ +public class SSLContextBuilder { + + /** + * Supports some version of SSL; may support other versions + */ + public static final String SSL = "SSL"; + /** + * Supports SSL version 2 or later; may support other versions + */ + public static final String SSLv2 = "SSLv2"; + /** + * Supports SSL version 3; may support other versions + */ + public static final String SSLv3 = "SSLv3"; + + /** + * Supports some version of TLS; may support other versions + */ + public static final String TLS = "TLS"; + /** + * Supports RFC 2246: TLS version 1.0 ; may support other versions + */ + public static final String TLSv1 = "TLSv1"; + /** + * Supports RFC 4346: TLS version 1.1 ; may support other versions + */ + public static final String TLSv11 = "TLSv1.1"; + /** + * Supports RFC 5246: TLS version 1.2 ; may support other versions + */ + public static final String TLSv12 = "TLSv1.2"; + + private String protocol = TLS; + private KeyManager[] keyManagers; + private TrustManager[] trustManagers; + private SecureRandom secureRandom = new SecureRandom(); + + + /** + * 创建 SSLContextBuilder + * + * @return SSLContextBuilder + */ + public static SSLContextBuilder create() { + return new SSLContextBuilder(); + } + + /** + * 设置协议。例如TLS等 + * + * @param protocol 协议 + * @return 自身 + */ + public SSLContextBuilder setProtocol(String protocol) { + if (StrUtil.isNotBlank(protocol)) { + this.protocol = protocol; + } + return this; + } + + /** + * 设置信任信息 + * + * @param trustManagers TrustManager列表 + * @return 自身 + */ + public SSLContextBuilder setTrustManagers(TrustManager... trustManagers) { + if (ArrayUtil.isNotEmpty(trustManagers)) { + this.trustManagers = trustManagers; + } + return this; + } + + /** + * 设置 JSSE key managers + * + * @param keyManagers JSSE key managers + * @return 自身 + */ + public SSLContextBuilder setKeyManagers(KeyManager... keyManagers) { + if (ArrayUtil.isNotEmpty(keyManagers)) { + this.keyManagers = keyManagers; + } + return this; + } + + /** + * 设置 SecureRandom + * + * @param secureRandom SecureRandom + * @return 自己 + */ + public SSLContextBuilder setSecureRandom(SecureRandom secureRandom) { + if (null != secureRandom) { + this.secureRandom = secureRandom; + } + return this; + } + + /** + * 构建{@link SSLContext} + * + * @return {@link SSLContext} + * @throws NoSuchAlgorithmException 无此算法 + * @throws KeyManagementException Key管理异常 + */ + public SSLContext build() throws NoSuchAlgorithmException, KeyManagementException { + SSLContext sslContext = SSLContext.getInstance(protocol); + sslContext.init(this.keyManagers, this.trustManagers, this.secureRandom); + return sslContext; + } + + /** + * 构建{@link SSLContext} + * + * @return {@link SSLContext} + * @throws IORuntimeException 包装 GeneralSecurityException异常 + */ + public SSLContext buildQuietly() throws IORuntimeException{ + try { + return build(); + } catch (GeneralSecurityException e) { + throw new IORuntimeException(e); + } + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/net/SSLUtil.java b/hutool-core/src/main/java/cn/hutool/core/net/SSLUtil.java new file mode 100644 index 000000000..1ec0e5c06 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/net/SSLUtil.java @@ -0,0 +1,49 @@ +package cn.hutool.core.net; + +import cn.hutool.core.io.IORuntimeException; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; + +/** + * SSL(Secure Sockets Layer 安全套接字协议)相关工具封装 + * + * @author looly + * @since 5.5.2 + */ +public class SSLUtil { + + /** + * 创建{@link SSLContext} + * + * @param protocol SSL协议,例如TLS等 + * @param keyManager 密钥管理器,{@code null}表示无 + * @param trustManager 信任管理器, {@code null}表示无 + * @return {@link SSLContext} + * @throws IORuntimeException 包装 GeneralSecurityException异常 + */ + public static SSLContext createSSLContext(String protocol, KeyManager keyManager, TrustManager trustManager) + throws IORuntimeException { + return createSSLContext(protocol, + keyManager == null ? null : new KeyManager[]{keyManager}, + trustManager == null ? null : new TrustManager[]{trustManager}); + } + + /** + * 创建和初始化{@link SSLContext} + * + * @param protocol SSL协议,例如TLS等 + * @param keyManagers 密钥管理器,{@code null}表示无 + * @param trustManagers 信任管理器, {@code null}表示无 + * @return {@link SSLContext} + * @throws IORuntimeException 包装 GeneralSecurityException异常 + */ + public static SSLContext createSSLContext(String protocol, KeyManager[] keyManagers, TrustManager[] trustManagers) throws IORuntimeException { + return SSLContextBuilder.create() + .setProtocol(protocol) + .setKeyManagers(keyManagers) + .setTrustManagers(trustManagers).buildQuietly(); + } + +} diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/SSLSocketFactoryBuilder.java b/hutool-http/src/main/java/cn/hutool/http/ssl/SSLSocketFactoryBuilder.java index 1d79f4328..1e138742c 100644 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/SSLSocketFactoryBuilder.java +++ b/hutool-http/src/main/java/cn/hutool/http/ssl/SSLSocketFactoryBuilder.java @@ -1,113 +1,122 @@ package cn.hutool.http.ssl; +import cn.hutool.core.net.SSLContextBuilder; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; -import javax.net.ssl.KeyManager; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; - -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.StrUtil; - /** * SSLSocketFactory构建器 - * @author Looly * + * @author Looly + * @see SSLContextBuilder */ -public class SSLSocketFactoryBuilder{ - - /** Supports some version of SSL; may support other versions */ - public static final String SSL = "SSL"; - /** Supports SSL version 2 or later; may support other versions */ - public static final String SSLv2 = "SSLv2"; - /** Supports SSL version 3; may support other versions */ - public static final String SSLv3 = "SSLv3"; - - /** Supports some version of TLS; may support other versions */ - public static final String TLS = "TLS"; - /** Supports RFC 2246: TLS version 1.0 ; may support other versions */ - public static final String TLSv1 = "TLSv1"; - /** Supports RFC 4346: TLS version 1.1 ; may support other versions */ - public static final String TLSv11 = "TLSv1.1"; - /** Supports RFC 5246: TLS version 1.2 ; may support other versions */ - public static final String TLSv12 = "TLSv1.2"; +public class SSLSocketFactoryBuilder { + + /** + * Supports some version of SSL; may support other versions + */ + public static final String SSL = SSLContextBuilder.SSL; + /** + * Supports SSL version 2 or later; may support other versions + */ + public static final String SSLv2 = SSLContextBuilder.SSLv2; + /** + * Supports SSL version 3; may support other versions + */ + public static final String SSLv3 = SSLContextBuilder.SSLv3; + + /** + * Supports some version of TLS; may support other versions + */ + public static final String TLS = SSLContextBuilder.TLS; + /** + * Supports RFC 2246: TLS version 1.0 ; may support other versions + */ + public static final String TLSv1 = SSLContextBuilder.TLSv1; + /** + * Supports RFC 4346: TLS version 1.1 ; may support other versions + */ + public static final String TLSv11 = SSLContextBuilder.TLSv11; + /** + * Supports RFC 5246: TLS version 1.2 ; may support other versions + */ + public static final String TLSv12 = SSLContextBuilder.TLSv12; + + SSLContextBuilder sslContextBuilder; + + /** + * 构造 + */ + public SSLSocketFactoryBuilder() { + this.sslContextBuilder = SSLContextBuilder.create(); + } - private String protocol = TLS; - private KeyManager[] keyManagers; - private TrustManager[] trustManagers = {new DefaultTrustManager()}; - private SecureRandom secureRandom = new SecureRandom(); - - /** * 创建 SSLSocketFactoryBuilder + * * @return SSLSocketFactoryBuilder */ - public static SSLSocketFactoryBuilder create(){ + public static SSLSocketFactoryBuilder create() { return new SSLSocketFactoryBuilder(); } - + /** * 设置协议 + * * @param protocol 协议 * @return 自身 */ - public SSLSocketFactoryBuilder setProtocol(String protocol){ - if(StrUtil.isNotBlank(protocol)){ - this.protocol = protocol; - } + public SSLSocketFactoryBuilder setProtocol(String protocol) { + this.sslContextBuilder.setProtocol(protocol); return this; } - + /** * 设置信任信息 - * + * * @param trustManagers TrustManager列表 * @return 自身 */ public SSLSocketFactoryBuilder setTrustManagers(TrustManager... trustManagers) { - if (ArrayUtil.isNotEmpty(trustManagers)) { - this.trustManagers = trustManagers; - } + this.sslContextBuilder.setTrustManagers(trustManagers); return this; } - + /** * 设置 JSSE key managers - * + * * @param keyManagers JSSE key managers * @return 自身 */ public SSLSocketFactoryBuilder setKeyManagers(KeyManager... keyManagers) { - if (ArrayUtil.isNotEmpty(keyManagers)) { - this.keyManagers = keyManagers; - } + this.sslContextBuilder.setKeyManagers(keyManagers); return this; } - + /** * 设置 SecureRandom + * * @param secureRandom SecureRandom * @return 自己 */ - public SSLSocketFactoryBuilder setSecureRandom(SecureRandom secureRandom){ - if(null != secureRandom){ - this.secureRandom = secureRandom; - } + public SSLSocketFactoryBuilder setSecureRandom(SecureRandom secureRandom) { + this.sslContextBuilder.setSecureRandom(secureRandom); return this; } - + /** * 构建SSLSocketFactory + * * @return SSLSocketFactory * @throws NoSuchAlgorithmException 无此算法 - * @throws KeyManagementException Key管理异常 + * @throws KeyManagementException Key管理异常 */ - public SSLSocketFactory build() throws NoSuchAlgorithmException, KeyManagementException{ - SSLContext sslContext = SSLContext.getInstance(protocol); - sslContext.init(this.keyManagers, this.trustManagers, this.secureRandom); - return sslContext.getSocketFactory(); + public SSLSocketFactory build() throws NoSuchAlgorithmException, KeyManagementException { + return this.sslContextBuilder.build().getSocketFactory(); } }