添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

以上Jdk原生支持(支持jks密钥库)的初始化方法,比较繁琐。可以借助Apache httpcore(支持jks密钥库)、netty sslContextBuilder(支持openssl crt+key.pk8)简化构建流程。

单向TLS

以下示例代码均使用如下证书相关文件:
在这里插入图片描述
ca根证书:
ca.crt+ca.key -> ca.p12 -> ca.jks
由openssl生成自签ca.crt+ca.key,然后导出ca.p12,最后由ca.p12转换成ca.jks
服务端证书:
emqx-dev.crt+emqx-dev.key -> emqx-dev.p12 -> emqx-dev.jks
emqx-dev.key -> emqx-dev.pk8

由ca根证书签署服务端证书emqx-dev.crt,然后导出emqx-dev.p12,最后由emqx-dev.p12转换成emqx-dev.jks
客户端证书:
emqx-dev-client.crt+emqx-dev-client.key -> emqx-dev-client.p12 -> emqx-dev-client.jks
emqx-dev-client.key -> emqx-dev-client.pk8

由ca根证书签署客户端证书emqx-dev-client.crt,然后导出emqx-dev-client.p12,最后由emqx-dev-client.p12转换成emqx-dev-client.jks

注:
关于证书的转换可参考:
证书格式及其转换
或者可使用xca等工具进行转换

Server端
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
 * Netty服务器 - tls单向验证
 * @author luohq
 * @date 2020/8/25
public class NettyServerWithTls {
    private int port;
    public NettyServerWithTls(int port) {
        this.port = port;
    public void run() throws Exception {
        /** 证书 */
        String basePath = "D:/idea_workspace/dev-utils/src/main/resources/";
        File certFile = new File(basePath + "jks/emqx-dev.crt");
        File keyFile = new File(basePath + "jks/emqx-dev.pk8");
        File rootFile = new File(basePath + "jks/ca.crt");
        File jksFile = new File(basePath + "jks/emqx-dev.jks");
        String jksKeyPassw = "mykeypass";
        String jksStorePassw = "mystorepass";
        /** ============ TLS - 单向 ===============*/
        SSLContext sslContext = null;
        /** 方式1: Java SSL(使用jks) - keyMangerFactory */
        //keyStore(仅需设置keyManager,用于管理服务端crt+key)
        //defaultType: jks 或者系统属性: keystore.type
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream(jksFile), jksStorePassw.toCharArray());
        //defaultAlgorithm: SunX509 或者系统属性: ssl.KeyManagerFactory.algorithm
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, jksKeyPassw.toCharArray());
        //生成SSLContext
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, null);
        /** 方式2: httpcore SSLContentBuilder(使用jks) - keyMaterial */
        sslContext = SSLContextBuilder.create()
                //keyStore
                .loadKeyMaterial(jksFile, jksStorePassw.toCharArray(), jksKeyPassw.toCharArray())
                .build();
        //方式1,2: 生成sslEngine
        SSLEngine sslEngine = sslContext.createSSLEngine();
        //是否客户端模式 - 服务端模式
        sslEngine.setUseClientMode(false);
        //是否需要验证客户端(双向验证) - 单向验证
        sslEngine.setNeedClientAuth(false);
        //pipeline.addFirst("ssl", new SslHandler(sslEngine));
        /** 方式3: netty sslContextBuilder server端 - 单向tls(使用crt+pk8) - keyManager  */
        SslContext nettySslContext = SslContextBuilder.forServer(certFile, keyFile)
                .clientAuth(ClientAuth.NONE)
                .build();
        //pipeline.addFirst("ssl", nettySslContext.newHandler(socketChannel.alloc()));
        EventLoopGroup bossGroup = new NioEventLoopGroup(); //用于处理服务器端接收客户端连接
        EventLoopGroup workerGroup = new NioEventLoopGroup(); //进行网络通信(读写)
        try {
            ServerBootstrap bootstrap = new ServerBootstrap(); //辅助工具类,用于服务器通道的一系列配置
            bootstrap.group(bossGroup, workerGroup) //绑定两个线程组
                    .channel(NioServerSocketChannel.class) //指定NIO的模式
                    .childHandler(new ChannelInitializer<SocketChannel>() { //配置具体的数据处理方式
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            /** 方式1,2: ssl handler */
                            //pipeline.addFirst("ssl", new SslHandler(sslEngine));
                            /** 方式3: netty sslContext */
                            pipeline.addFirst("ssl", nettySslContext.newHandler(socketChannel.alloc()));
                            //业务handler
                            pipeline.addLast(new ServerHandler());
                    .option(ChannelOption.SO_BACKLOG, 128) //设置TCP缓冲区
                    .childOption(ChannelOption.SO_SNDBUF, 32 * 1024) //设置发送数据缓冲大小
                    .childOption(ChannelOption.SO_RCVBUF, 32 * 1024) //设置接受数据缓冲大小
                    .childOption(ChannelOption.SO_KEEPALIVE, true); //保持连接
            ChannelFuture future = bootstrap.bind(port).sync();
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
    public class ServerHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            //do something msg
            ByteBuf buf = (ByteBuf) msg;
            byte[] data = new byte[buf.readableBytes()];
            buf.readBytes(data);
            String request = new String(data, "utf-8");
            System.out.println("Server Recv from Client: " + request);
            //写给客户端
            String response = "888";
            System.out.println("Server send to Client: " + response);
            ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            cause.printStackTrace();
            ctx.close();
    public static void main(String[] args) throws Exception {
        new NettyServerWithTls(8379).run();
Client端
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.util.ReferenceCountUtil;
import org.apache.http.ssl.SSLContextBuilder;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
 * Netty客户端 - tls单向验证
 * @author luohq
 * @date 2020/8/25
public class NettyClientWithTls {
    public static void main(String[] args) throws Exception {
        String basePath = "D:/idea_workspace/dev-utils/src/main/resources/";
        File rootFile = new File(basePath + "jks/ca.crt");
        File jksFile = new File(basePath + "jks/emqx-dev.jks");
        String jksStorePassw = "mystorepass";
        /** ============ TLS - 单向 ===============*/
        SSLContext sslContext = null;
        /** 方式1: Java SSL(使用jks) - trustManagerFactory */
        //trustKeyStore
        KeyStore tks = KeyStore.getInstance(KeyStore.getDefaultType());
        tks.load(new FileInputStream(jksFile), jksStorePassw.toCharArray());
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(tks);
        //生成SSLContext
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);
        /** 方式2: httpcore SSLContentBuilder(使用jks) - trustMaterial */
        sslContext = SSLContextBuilder.create()
                //trustKeyStore
                .loadTrustMaterial(jksFile, jksStorePassw.toCharArray())
                .build();
        //方式1,2: 生成sslEngine
        SSLEngine sslEngine = sslContext.createSSLEngine();
        //是否客户端模式 - 客户端模式
        sslEngine.setUseClientMode(true);
        //是否需要验证客户端(双向验证) - 单向验证
        sslEngine.setNeedClientAuth(false);
        //pipeline.addFirst("ssl", new SslHandler(sslEngine));
        /** 方式3: netty sslContextBuilder - 客户端 trustCa - 单向 (使用ca) - trustManager */
        SslContext nettySslContext = SslContextBuilder.forClient()
                //trustKeyStore(此处指定ca.crt或者server.crt均可)
                .trustManager(rootFile)
                .build();
        //pipeline.addFirst("ssl", nettySslContext.newHandler(socketChannel.alloc()));
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(workerGroup)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        /** 方式1,2: ssl handler(trust ca) */
                        //pipeline.addFirst("ssl", new SslHandler(sslEngine));
                        /** 方式3: netty sslContext */
                        pipeline.addFirst("ssl", nettySslContext.newHandler(socketChannel.alloc()));
                        pipeline.addLast(new ClientHandler());
                });
        ChannelFuture future = bootstrap.connect("127.0.0.1", 8379).sync();
        String sendMsg = "777";
        System.out.println("Client send to Server:" + sendMsg);
        future.channel().writeAndFlush(Unpooled.copiedBuffer(sendMsg.getBytes()));
        future.channel().closeFuture().sync();
        workerGroup.shutdownGracefully();
    public static class ClientHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            try {
                ByteBuf buf = (ByteBuf) msg;
                byte[] data = new byte[buf.readableBytes()];
                buf.readBytes(data);
                System.out.println("Client recv from Server:" + new String(data).trim());
            } finally {
                ReferenceCountUtil.release(msg);
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            cause.printStackTrace();
            ctx.close();

双向TLS

server端
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
 * Netty服务器 - 双向tls验证
 * @author luohq
 * @date 2020/8/25
public class NettyServerWithMtls {
    private int port;
    public NettyServerWithMtls(int port) {
        this.port = port;
    public void run() throws Exception {
        /** 证书 */
        String basePath = "D:/idea_workspace/dev-utils/src/main/resources/";
        File certFile = new File(basePath + "jks/emqx-dev.crt");
        File keyFile = new File(basePath + "jks/emqx-dev.pk8");
        File rootFile = new File(basePath + "jks/ca.crt");
        File jksServerFile = new File(basePath + "jks/emqx-dev.jks");
        File jksCaFile = new File(basePath + "jks/ca.jks");
        String jksKeyPassw = "mykeypass";
        String jksStorePassw = "mystorepass";
        /** ============ TLS - 双向 ===============*/
        SSLContext sslContext = null;
        /** 方式1:Java SSL(使用jks) - server端keyManagerFactory+trustManagerFactory */
        /** keyStore */
        //defaultType: jks 或者系统属性: keystore.type"
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream(jksServerFile), jksStorePassw.toCharArray());
        //defaultAlgorithm: SunX509 或者系统属性: ssl.KeyManagerFactory.algorithm
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, jksKeyPassw.toCharArray());
        /** trustKeyStore */
        KeyStore tks = KeyStore.getInstance(KeyStore.getDefaultType());
        tks.load(new FileInputStream(jksCaFile), jksStorePassw.toCharArray());
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(tks);
        //生成SSLContext
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        /** 方式2: httpcore SSLContentBuilder(使用jks) - server端keyMaterial+trustMaterial */
        sslContext = SSLContextBuilder.create()
                //keyStore
                .loadKeyMaterial(jksServerFile, jksStorePassw.toCharArray(), jksKeyPassw.toCharArray())
                //trustKeyStore
                .loadTrustMaterial(jksCaFile, jksStorePassw.toCharArray())
                .build();
        //方式1,2: 生成sslEngine
        SSLEngine sslEngine = sslContext.createSSLEngine();
        //是否客户端模式 - 服务端模式
        sslEngine.setUseClientMode(false);
        //是否需要验证客户端(双向验证) - 双向验证
        sslEngine.setNeedClientAuth(true);
        //pipeline.addFirst("ssl", new SslHandler(sslEngine));
        /** 方式3: netty sslContextBuilder server端 - 双向tls(使用server端crt+pk8+ca) */
        SslContext nettySslContext = SslContextBuilder.forServer(certFile, keyFile)
                .trustManager(rootFile)
                .clientAuth(ClientAuth.REQUIRE)
                .build();
        EventLoopGroup bossGroup = new NioEventLoopGroup(); //用于处理服务器端接收客户端连接
        EventLoopGroup workerGroup = new NioEventLoopGroup(); //进行网络通信(读写)
        try {
            ServerBootstrap bootstrap = new ServerBootstrap(); //辅助工具类,用于服务器通道的一系列配置
            bootstrap.group(bossGroup, workerGroup) //绑定两个线程组
                    .channel(NioServerSocketChannel.class) //指定NIO的模式
                    .childHandler(new ChannelInitializer<SocketChannel>() { //配置具体的数据处理方式
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            /** 方式1,2: ssl handler */
                            //pipeline.addFirst("ssl", new SslHandler(sslEngine));
                            /** 方式3: netty sslContext */
                            pipeline.addFirst("ssl", nettySslContext.newHandler(socketChannel.alloc()));
                            //业务handler
                            pipeline.addLast(new ServerHandler());
                    .option(ChannelOption.SO_BACKLOG, 128) //设置TCP缓冲区
                    .childOption(ChannelOption.SO_SNDBUF, 32 * 1024) //设置发送数据缓冲大小
                    .childOption(ChannelOption.SO_RCVBUF, 32 * 1024) //设置接受数据缓冲大小
                    .childOption(ChannelOption.SO_KEEPALIVE, true); //保持连接
            ChannelFuture future = bootstrap.bind(port).sync();
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
    public class ServerHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            //do something msg
            ByteBuf buf = (ByteBuf) msg;
            byte[] data = new byte[buf.readableBytes()];
            buf.readBytes(data);
            String request = new String(data, "utf-8");
            System.out.println("Server Recv from Client: " + request);
            //写给客户端
            String response = "888";
            System.out.println("Server send to Client: " + response);
            ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            cause.printStackTrace();
            ctx.close();
    public static void main(String[] args) throws Exception {
        new NettyServerWithMtls(8379).run();
client端
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.util.ReferenceCountUtil;
import org.apache.http.ssl.SSLContextBuilder;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
 * Netty客户端 - 双向tls验证
 * @author luohq
 * @date 2020/8/25
public class NettyClientWithMtls {
    public static void main(String[] args) throws Exception {
        String basePath = "D:/idea_workspace/dev-utils/src/main/resources/";
        File certFile = new File(basePath + "jks/emqx-dev.crt");
        File keyFile = new File(basePath + "jks/emqx-dev.pk8");
        File rootFile = new File(basePath + "jks/ca.crt");
        File jksServerFile = new File(basePath + "jks/emqx-dev.jks");
        File jksCaFile = new File(basePath + "jks/ca.jks");
        File jksClientFile = new File(basePath + "jks/emqx-dev-client.jks");
        String jksKeyPassw = "mykeypass";
        String jksStorePassw = "mystorepass";
        /** ============ TLS - 双向 ===============*/
        SSLContext sslContext = null;
        /** 方式1: Java SSL(使用jks) - 客户端keyManagerFactory+服务端trustManagerFactory */
        //keyStore
        //defaultType: jks 或者系统属性: keystore.type"
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream(jksClientFile), jksStorePassw.toCharArray());
        //defaultAlgorithm: SunX509 或者系统属性: ssl.KeyManagerFactory.algorithm
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, jksKeyPassw.toCharArray());
        //trustKeyStore
        KeyStore tks = KeyStore.getInstance(KeyStore.getDefaultType());
        //此处暴露server.jks 或 ca.jks均可通过验证
        tks.load(new FileInputStream(jksCaFile), jksStorePassw.toCharArray());
        //tks.load(new FileInputStream(jksServerFile), jksStorePassw.toCharArray());
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(tks);
        //生成SSLContext
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        /** 方式2: httpcore SSLContentBuilder(使用jks) - 客户端keyMaterial+服务端trustMaterial */
        sslContext = SSLContextBuilder.create()
                //keyStore
                .loadKeyMaterial(jksClientFile, jksStorePassw.toCharArray(), jksKeyPassw.toCharArray())
                //trustKeyStore
                .loadTrustMaterial(jksCaFile, jksStorePassw.toCharArray())
                .build();
        //方式1,2: 生成sslEngine
        SSLEngine sslEngine = sslContext.createSSLEngine();
        //是否客户端模式 - 客户端模式
        sslEngine.setUseClientMode(true);
        //是否需要验证客户端(双向验证) - 双向验证
        sslEngine.setNeedClientAuth(true);
        //pipeline.addFirst("ssl", new SslHandler(sslEngine));
        /** 方式3: netty sslContextBuilder(使用客户端cert+key.pk8,ca) - 客户端keyManager+ca端trustManager */
        SslContext nettySslContext = SslContextBuilder.forClient()
                //客户端crt+key.pk8
                .keyManager(certFile, keyFile)
                //ca根证书
                .trustManager(rootFile)
                //双向验证
                .clientAuth(ClientAuth.REQUIRE)
                .build();
        //pipeline.addFirst("ssl", nettySslContext.newHandler(socketChannel.alloc()));
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(workerGroup)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        /** 方式1,2: ssl handler(trust ca) */
                        //pipeline.addFirst("ssl", new SslHandler(sslEngine));
                        /** 方式3: netty sslContext */
                        pipeline.addFirst("ssl", nettySslContext.newHandler(socketChannel.alloc()));
                        pipeline.addLast(new ClientHandler());
                });
        ChannelFuture future = bootstrap.connect("127.0.0.1", 8379).sync();
        String sendMsg = "777";
        System.out.println("Client send to Server:" + sendMsg);
        future.channel().writeAndFlush(Unpooled.copiedBuffer(sendMsg.getBytes()));
        future.channel().closeFuture().sync();
        workerGroup.shutdownGracefully();
    public static class ClientHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            try {
                ByteBuf buf = (ByteBuf) msg;
                byte[] data = new byte[buf.readableBytes()];
                buf.readBytes(data);
                System.out.println("Client recv from Server:" + new String(data).trim());
            } finally {
                ReferenceCountUtil.release(msg);
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            cause.printStackTrace();
            ctx.close();

KeyStore读取P12

keyStore除了读取JKS外,还可以读取P12密钥库,以上代码中使用KeyStore读取JKS的地方都可以换成读取P12(如使用openssl生成的证书或其他X.509证书都以直接转到p12而无需再转到jks)

	/** 证书 */
	 String basePath = "D:/idea_workspace/dev-utils/src/main/resources/";
	 File p12File = new File(basePath + "jks/emqx-dev.p12");
	 String p12Passw = "myp12pass";
	 ...
	 /** 方式1: Java SSL(使用p12) - keyMangerFactory */
	 //keyStore(仅需设置keyManager,用于管理服务端crt+key)
	 //defaultType: jks 或者系统属性: keystore.type
	 KeyStore ks = KeyStore.getInstance("PKCS12");
	 ks.load(new FileInputStream(p12File), p12Passw.toCharArray());
	 //defaultAlgorithm: SunX509 或者系统属性: ssl.KeyManagerFactory.algorithm
	 KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
	 kmf.init(ks, p12Passw.toCharArray());
	 //生成SSLContext
	 sslContext = SSLContext.getInstance("TLS");
	 sslContext.init(kmf.getKeyManagers(), null, null);
	 ...

TODO 自定义验证规则

例如对证书中的特定subject进行验证(如设备ID等)

时光流逝,我们心爱的ASP.NET也步入了4.0的时代,微软在ASP.NET 4.0中对很多特性做了修改。比如我将要讨论的控件ID机制就是其中之一。 在ASP.NET 4.0之前我们总是要为控件的ClientID头疼,比如明明一个叫lblName的Label放在一个叫做grd的GridView里面后,在页面上改Label的ID就变成了诸如grd_clt02_lblName的一长串... 代码中,我们在创建EchoServer时指定了SslContext对象,用于启用SSL和TLS协议支持。以上代码中,我们在EchoServerHandler的channelActive方法中添加了一个SslHandler处理器,并将其添加到ChannelPipeline中。Netty支持使用SSL和TLS协议进行加密通信,可以在保证通信安全的同时,保证数据传输的完整性和可靠性。例如,我们可以使用下面的代码创建一个EchoServer,并指定SSL和TLS协议支持。然后,我们调用sync方法等待服务器关闭。 这次使用的Netty是最新的5.0 Alpha2版本,下载地址是:http://dl.bintray.com/netty/downloads/netty-5.0.0.Alpha2.tar.bz2,发布时间是2015年3月,到现在快一年了,咋还不更新呢?有些奇怪…… 制作一张自签证书(jks格式) #keytool -genkey -keysize 2048 -validity 3... 在使用spark-submit提交Spark任务一般有以下参数:./bin/spark-submit \ --class <main-class> \ --master <master-url> \ --deploy-mode <deploy-mode> \ --conf <key>=<value> \ ... # other options <application-jar 以前我们可以通过ClientID在JavaScript脚本中服务器端控件.比如: document.getElementById("&lt;%=控件.ClientID %&gt;"); 这种方式不方便,而且如果在有数据绑定的控件中嵌套着子控件,则访问更不太方便了. 现在,在Asp.Net4中,对于控件增加了一种新的属性,名为ClientIDMode.通过设置ClientIDMode,我... 服务端实现 客户端代码 调试观测Netty Tls实现TLS作用如果没有使用TLS的话会存在一下风险(1) 窃听风险(eavesdropping):第三方可以获知通信内容。(2) 篡改风险(tamper 在前面的文章中我们讲过了如何在netty中构造客户端分别使用tcp和udp协议向DNS服务器请求消息。在请求的过程中并没有进行消息的加密,所以这种请求是不安全的。那么有同学会问了,就是请求解析一个域名的IP地址而已,还需要安全通讯吗?事实上,不加密的DNS查询消息是很危险的,如果你在访问一个重要的网站时候,DNS查询消息被监听或者篡改,有可能你收到的查询返回IP地址并不是真实的地址,而是被篡改之后的地址,从而打开了钓鱼网站或者其他恶意的网站,从而造成了不必要的损失。所以DNS查询也是需要保证安全的。 1、Netty SSL安全特性 JDK的安全类库提供了 javax.net.ssl.SSLSocket和javax.net.ssl.SSLServerSocket类库用于支持SSL/TLS安全传输,对于NIO非阻塞 Socket通信,JDK并没有提供现成可用的类库简化用户开发。 Netty通过JDK的 SSLEngine,以 SslHandler的方式提供对SSL/TLS安全传输的支持,极大的简... 一、证书准备      要使用ssl双向验证,就必须先要生成服务端和客户端的证书,并相互添加信任,具体流程如下(本人调试这个用例的时候,花了很多时间来验证证书是否正确,以及握手失败的原因,这里证书生成过程只要按流程走,本人能保证绝对没有问题) 现在打开cmd,在哪个目录下打开,证书就会放在哪个目录下: 第一步:   生成Netty服务端私钥和证书仓库命令  keytool -genkey ... 异步的SSL和TLSNetty的SSL和TLS实现是异步的,这意味着在进行SSL和TLS握手时,不会阻塞线程,从而提高了应用程序的吞吐量和性能。SSL和TLS的实现:Netty提供了SSL和TLS的实现,使得开发者可以在应用程序中使用这些协议来保护数据的安全性。可扩展的SSL和TLSNetty的SSL和TLS实现是可扩展的,允许开发者对其进行自定义,以满足特定应用程序的需求。总的来说,Netty的SSL和TLS支持使得开发者可以方便地为Netty应用程序添加安全性,保护数据的机密性和完整性。 文档主要是为了做一个关于Netty、SSL/TLS方面的概括性介绍,着重于具体编码实现;源代码例子实现了Socket服务端和客户端,以及Http服务端和客户端,并实现SSL/TLS支持。