Netty服务添加https支持,jdk 证书

本文介绍了如何使用JDK的keytool生成keystore,以及如何在Java中通过SSLContext创建SSLEngine,用于Netty服务器端的安全通信。此外,还展示了如何在客户端使用Apache HttpClient跳过证书验证进行HTTPS连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、使用JDK自带的keytool生成一个keystore,这个keystore是服务端使用的,直接在bin目录下执行

keytool -genkey -alias netty -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -keystore D:/test/netty.keystore -storepass 123456

2、新建一个安全工具类,用于返回一个SSLEngine

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import java.security.KeyStore;
import java.security.Security;
/**
 * @description: SSL服务器端认证
 */
public class HttpSslContextFactory {
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpSslContextFactory.class);
//    private static final String PROTOCOL = "SSLv2";
    private static final String PROTOCOL = "SSLv3";//客户端可以指明为SSLv3或者TLSv1.2
    /**针对于服务器端配置*/
    private static SSLContext sslContext = null;
    static {
        String algorithm = Security
                .getProperty("ssl.KeyManagerFactory.algorithm");
        if (algorithm == null) {
            algorithm = "SunX509";
        }
        SSLContext serverContext = null;
        try {
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(HttpsKeyStore.getKeyStoreStream(), HttpsKeyStore.getKeyStorePassword());
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
            kmf.init(ks, HttpsKeyStore.getCertificatePassword());
            serverContext = SSLContext.getInstance(PROTOCOL);
            serverContext.init(kmf.getKeyManagers(), null, null);
        } catch (Exception e) {
            LOGGER.error("初始化server SSL失败", e);
            throw new Error("Failed to initialize the server SSLContext", e);
        }
        sslContext = serverContext;
    }
    public static SSLEngine createSSLEngine() {
        SSLEngine sslEngine = sslContext.createSSLEngine();
        sslEngine.setUseClientMode(false);
        sslEngine.setNeedClientAuth(false);
        return sslEngine ;
    }
}

上面的有一个HttpsKeyStore类如下,分别如下:

 


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class HttpsKeyStore {
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpsKeyStore.class);

    /**
     * 读取密钥
     * @version V1.0.0
     * @return InputStream
     */
    public static InputStream getKeyStoreStream() {
        InputStream inStream = null;
        try {
            inStream = new FileInputStream(VarConstant.keystorePath);
        } catch (FileNotFoundException e) {
            LOGGER.error("读取密钥文件失败", e);
        }
        return inStream;
    }

    /**
     * 获取安全证书密码 (用于创建KeyManagerFactory)
     * @version V1.0.0
     * @return char[]
     */
    public static char[] getCertificatePassword() {
        return VarConstant.certificatePassword.toCharArray();
    }

    /**
     * 获取密钥密码(证书别名密码) (用于创建KeyStore)
     * @version V1.0.0
     * @return char[]
     */
    public static char[] getKeyStorePassword() {
        return VarConstant.keystorePassword.toCharArray();
    }
}

其中常量类VarConstant的几个属性如下,其他的不再粘贴:

 

//SSL
public static Boolean sslEnabled = true;
public static String keystorePath = "D:/test/netty.keystore";
public static String certificatePassword = "123456";
public static String keystorePassword = "123456";

3、上面的步骤做好之后,我们只需给Netty的pipeline的添加第一个的handler,如下:

 

//是否开启SSL
if (VarConstant.sslEnabled) {
   //务必放在第一位
   ch.pipeline().addLast("sslHandler", new SslHandler(HttpSslContextFactory.createSSLEngine()));
}

4、基本的步骤就是上面这样子,如果要添加双向认证,还需另外生成客户端证书,通过以上这种方式,客户端只需跳过证书认证即可,如使用apache httpclients,跳过认证代码如下:

 

public static CloseableHttpClient getHttpsClient(){
    SSLContext sslContext = null;
    try {
        //SSLv3或者TLSv1.2都可以
        sslContext = new SSLContextBuilder().useProtocol("TLSv1.2").loadTrustMaterial(null, new TrustStrategy() {
            // 默认信任所有证书
            public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                return true;
            }
        }).build();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    }
    HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,hostnameVerifier);

    SocketConfig socketConfig = SocketConfig.custom()
            .setSoKeepAlive(true)
            .setTcpNoDelay(true)
            .setSoReuseAddress(true)
            .build();
    RequestConfig requestConfig = RequestConfig.custom()
            .setConnectTimeout(30000)
            .setSocketTimeout(30000).build();

    HttpClientBuilder clientBuilder = HttpClientBuilder.create();
    return clientBuilder
            .setSSLSocketFactory(sslsf)
            .setDefaultRequestConfig(requestConfig)
            .setDefaultSocketConfig(socketConfig).build();
}
Netty是一个高性能、异步事件驱动的网络应用框架,用于快速构建高效的服务器和客户端通信。为了集成SSL/TLS支持HTTPS,你可以按照以下步骤操作: 1. **添加依赖**:在你的项目中引入相关的SSL/TLS库,如JSSE(Java Secure Socket Extension),它已经包含在标准的JDK中。 ```java // 如果你使用的是Maven <dependency> <groupId>io.netty</groupId> <artifactId>netty-tcnative-boringssl-static</artifactId> </dependency> // 或者Gradle implementation 'io.netty:netty-tcnative-boringssl-static' ``` 2. **创建SSLContext**:使用`KeyManagerFactory`和`TrustManagerFactory`从Keystore加载SSL证书和密钥对。 ```java KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream("path_to_keystore"), "password".toCharArray()); KeyManager[] keyManagers = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()) .load(keyStore, "password".toCharArray()).getKeyManagers(); TrustManager[] trustManagers = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) .load(keyStore, "password".toCharArray()).getTrustManagers(); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagers, trustManagers, new SecureRandom()); ``` 3. **配置ChannelInitializer**:在`Bootstrap`初始化时,设置一个`ServerBootstrap`的ChannelInitializer,该初始化器会为每个连接创建一个新的`SSLEngine`并绑定到通道上。 ```java Bootstrap b = new Bootstrap(); b.group(...).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new SslHandler(sslContext)); // ... 其他管道配置 } }); ``` 4. **启动服务**:使用`bind`方法监听特定端口并开始处理HTTPS请求。 ```java b.bind(port).sync(); ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yzgu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值