
com.jianggujin.socket.JSSLSocketClient Maven / Gradle / Ivy
/**
* Copyright 2018 jianggujin (www.jianggujin.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jianggujin.socket;
import java.io.IOException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import com.jianggujin.socket.util.JSSLContextUtils;
import com.jianggujin.socket.util.JSSLSocketUtils;
public class JSSLSocketClient extends JSocketClient {
/** 默认安全套接字协议名称,值为:TLS */
private static final String DEFAULT_PROTOCOL = "TLS";
/** 安全模式, True - 隐式 / False - 显示 */
private final boolean isImplicit;
/** 套接字使用的安全协议,例如: SSL/TLS */
private final String protocol;
/** 安全套接字协议的实现 */
private SSLContext context = null;
/** 密码套件,SSLSockets有默认设置,所以不需要初始化为必须的 */
private String[] suites = null;
/** 协议版本 */
private String[] protocols = null;
/** 信任管理器,如果为null则使用系统默认管理器 */
private TrustManager trustManager = null;
/** 密钥管理器,如果为null则使用系统默认管理器 */
private KeyManager keyManager = null;
/** 主机名验证 */
private HostnameVerifier hostnameVerifier = null;
/** 使用java 1.7+ HTTPS端点识别算法 */
private boolean tlsEndpointChecking;
/**
* Constructor for SMTPSClient, using {@link #DEFAULT_PROTOCOL} i.e. TLS Sets
* security mode to explicit (isImplicit = false).
*/
public JSSLSocketClient() {
this(DEFAULT_PROTOCOL, false);
}
public JSSLSocketClient(boolean implicit) {
this(DEFAULT_PROTOCOL, implicit);
}
public JSSLSocketClient(String proto) {
this(proto, false);
}
public JSSLSocketClient(String proto, boolean implicit) {
protocol = proto;
isImplicit = implicit;
}
public JSSLSocketClient(boolean implicit, SSLContext ctx) {
isImplicit = implicit;
context = ctx;
protocol = DEFAULT_PROTOCOL;
}
public JSSLSocketClient(SSLContext context) {
this(false, context);
}
@Override
protected void connectAction() throws IOException {
if (isImplicit) {
performSSLNegotiation();
}
super.connectAction();
// 显示模式 - 不作任何处理,用户调用execTLS()
}
/**
* 延迟初始化SSLContext
*
* @throws IOException
*/
private void initSSLContext() throws IOException {
if (context == null) {
context = JSSLContextUtils.createSSLContext(protocol, getKeyManager(), getTrustManager());
}
}
/**
* SSL/TLS协商。获取连接SSL套接字进行握手处理。
*
* @throws IOException
*/
private void performSSLNegotiation() throws IOException {
initSSLContext();
SSLSocketFactory ssf = context.getSocketFactory();
String host = (this.hostname != null) ? this.hostname : getRemoteAddress().getHostAddress();
int port = getRemotePort();
SSLSocket socket = (SSLSocket) ssf.createSocket(this.socket, host, port, true);
socket.setEnableSessionCreation(true);
socket.setUseClientMode(true);
if (tlsEndpointChecking) {
JSSLSocketUtils.enableEndpointNameVerification(socket);
}
if (protocols != null) {
socket.setEnabledProtocols(protocols);
}
if (suites != null) {
socket.setEnabledCipherSuites(suites);
}
socket.startHandshake();
this.socket = socket;
this.input = socket.getInputStream();
this.output = socket.getOutputStream();
if (hostnameVerifier != null && !hostnameVerifier.verify(host, socket.getSession())) {
throw new SSLHandshakeException("Hostname doesn't match certificate");
}
}
/**
* 获得密钥管理器
*
* @return
*/
public KeyManager getKeyManager() {
return keyManager;
}
/**
* 设置密钥管理器
*
* @param newKeyManager
*/
public void setKeyManager(KeyManager newKeyManager) {
keyManager = newKeyManager;
}
/**
* 将密码套件设置为启用以供此连接使用
*
* @param cipherSuites
*/
public void setEnabledCipherSuites(String[] cipherSuites) {
suites = new String[cipherSuites.length];
System.arraycopy(cipherSuites, 0, suites, 0, cipherSuites.length);
}
/**
* 获得当前启用以供此连接使用的 SSL 密码套件的名称
*
* @return
*/
public String[] getEnabledCipherSuites() {
if (this.socket instanceof SSLSocket) {
return ((SSLSocket) this.socket).getEnabledCipherSuites();
}
return null;
}
/**
* 设置启用以供此连接使用的协议版本
*
* @param protocolVersions
*/
public void setEnabledProtocols(String[] protocolVersions) {
protocols = new String[protocolVersions.length];
System.arraycopy(protocolVersions, 0, protocols, 0, protocolVersions.length);
}
/**
* 获得当前启用以供此连接使用的协议版本的名称
*
* @return
*/
public String[] getEnabledProtocols() {
if (this.socket instanceof SSLSocket) {
return ((SSLSocket) this.socket).getEnabledProtocols();
}
return null;
}
/**
* 开始使用安全链接
*
* @throws IOException
*/
public void execTLS() throws IOException {
performSSLNegotiation();
}
/**
* 获得信任管理器
*
* @return
*/
public TrustManager getTrustManager() {
return trustManager;
}
/**
* 设置信任管理器
*
* @param newTrustManager
*/
public void setTrustManager(TrustManager newTrustManager) {
trustManager = newTrustManager;
}
/**
* 获得主机名验证
*
* @return
*/
public HostnameVerifier getHostnameVerifier() {
return hostnameVerifier;
}
/**
* 设置主机验证
*
* @param newHostnameVerifier
*/
public void setHostnameVerifier(HostnameVerifier newHostnameVerifier) {
hostnameVerifier = newHostnameVerifier;
}
/**
* 是否使用java 1.7+ HTTPS端点识别算法
*
* @return
*/
public boolean isEndpointCheckingEnabled() {
return tlsEndpointChecking;
}
/**
* 设置是否使用java 1.7+ HTTPS端点识别算法
*
* @param enable
*/
public void setEndpointCheckingEnabled(boolean enable) {
tlsEndpointChecking = enable;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy