转载 Netty tls验证
https://blog.csdn.net/luo15242208310/article/details/108215019
目录
Java ssl
单向TLS
Server端
Client端
双向TLS
server端
client端
KeyStore读取P12
TODO 自定义验证规则
Java ssl
netty中使用SslHandler进行tls验证拦截,通过Java Ssl相关接口+jks密钥库,生成SslHandler流程如下图:
ks.load(jksFile, storePassw)
kmf.init(ks, keyPassw)
tks.load(jksFile, storePassw)
tmf.init(tks)
sslContext.init(kmf.km, tkf.tkm)
sslContext.init(kmf.km, tkf.tkm)
sslContext.createSslEngine
new SslHander(sslEngine)
jksFile
keyStore
keyManagerFactory
trustKeyStore
trustManagerFactory
sslContext
sslEngine
sslHander
以上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等)
转载 Netty tls验证的更多相关文章
- [转载] Netty
转载自http://lippeng.iteye.com/blog/1907279 Netty是什么? 本质:JBoss做的一个Jar包 目的:快速开发高性能.高可靠性的网络服务器和客户端程序 优点:提 ...
- [转载] Netty源码分析
转载自http://blog.csdn.net/kobejayandy/article/details/11836813 Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高 ...
- [转载] Netty教程
转载自http://blog.csdn.net/kobejayandy/article/details/11493717 先啰嗦两句,如果你还不知道Netty是做什么的能做什么.那可以先简单的搜索了解 ...
- 【转载】Cadence验证仿真工具IUS和IES
本博客转自: cadence验证仿真工具IUS和IES | 骏的世界http://www.lujun.org.cn/?p=3714 cadence验证仿真工具IUS和IES cadence,有两大验证 ...
- 解决ssh无操作自动断开[转载,已经验证]
用SSH远程,如果几分钟没有任何操作,连接就会断开,必须重新登陆才行,非常麻烦,一般修改2个地方3项即可解决问题: 1.终端键入:echo $TMOUT 如果显示空白,表示没有设置,等于使 ...
- 协议森林17 我和你的悄悄话 (SSL/TLS协议)
作者:Vamei 出处:http://www.cnblogs.com/vamei 转载请先与我联系. TLS名为传输层安全协议(Transport Layer Protocol),这个协议是一套加密的 ...
- 洗礼灵魂,修炼python(58)--爬虫篇—【转载】urllib3模块
urllib3 1.简介 urllib3相比urllib,urlib2,又有些一些新的功能,可以实现很多东西,而这个模块有点特殊的是,并且还可以同时存在于python2和python3,但说实话,用的 ...
- python urllib和urllib3包使用(转载于)
urllib.request 1. 快速请求 2.模拟PC浏览器和手机浏览器 3.Cookie的使用 4.设置代理 urllib.error URLError HTTPError urllib.par ...
- EXCHANGE 2013 TLS传输层安全
默认情况下,SMTP流量是不被加密的,这就导致在公网上进行邮件沟通就像是在广播一样,任何人拦截到该邮件都可以轻而易举的读取其内容.但是现实场景中有许多敏感信息是通过邮件来进行发送的,所以其中一种保护邮 ...
- OpenID Connect Core 1.0(五)使用授权码流验证(下)
3.1.2.6 验证错误响应(Authentication Error Response) 验证错误响应是一个OAuth 2.0授权错误响应消息,是RP发送授权请求的消息,由OP授权终结点的响应返回. ...
随机推荐
- fastjson序列化导致prometheus返回监控数据格式错乱
在springboot 中集成prometheus的监控时遇见问题. 因为项目里在StaticResourceConfig配置了fastjson 序列化,导致prometheus接口返回数据被转化为j ...
- 基于Jenkins + Argo 实现多集群的持续交付
作者:周靖峰,青云科技容器顾问,云原生爱好者,目前专注于 DevOps,云原生领域技术涉及 Kubernetes.KubeSphere.Argo. 前文概述 前面我们已经掌握了如何通过 Jenkins ...
- KubeSphere 社区双周报 | OpenFunction v1.0.0-rc.0 发布
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...
- Octomap的学习
什么是octomap? RGBD SLAM的目的有两个:估计机器人的轨迹,并建立正确的地图.地图有很多种表达方式,比如特征点地图.网格地图.拓扑地图等等.在<一起做>系列中,我们使用的地图 ...
- vivo 轩辕文件系统:AI 计算平台存储性能优化实践
在早期阶段,vivo AI 计算平台使用 GlusterFS 作为底层存储基座.随着数据规模的扩大和多种业务场景的接入,开始出现性能.维护等问题.为此,vivo 转而采用了自研的轩辕文件系统,该系统是 ...
- 开源 PHP 商城项目 CRMEB 安装和使用教程
说到电商系统,很多人第一反应可能是 Shopify 或 Magento.没错,这些平台确实功能强大,但是...它们也太强大了,不仅复杂还昂贵,对于刚起步的创业者来说简直是压力山大. 但是从零开始开发一 ...
- docker REPOSITORY 改名
创建新的名称: docker tag oldname:tag newname:tag 删除旧的名称: docker rmi oldname:tag
- 基于Java+SpringBoot心理测评心理测试系统功能实现三
一.前言介绍: 1.1 项目摘要 心理测评和心理测试系统在当代社会中扮演着越来越重要的角色.随着心理健康问题日益受到重视,心理测评和心理测试系统作为评估个体心理状态.诊断心理问题.制定心理治疗方案的工 ...
- CLIPFit:不绕弯子,直接微调比提示微调和适配器微调更好 | EMNLP'24
来源:晓飞的算法工程笔记 公众号,转载请注明出处 论文: Vision-Language Model Fine-Tuning via Simple Parameter-Efficient Modifi ...
- ubuntu系统安装wps后语言是英文的问题
如果安装ubuntu系统后,在里面安装wps的时候,发现都是英文,无法切换为中文,可以这样操作. 此时点击这里新建一个word空白文档 点击这里新建文档 点击这里显示语言 点击下面的 简体中文 再点击 ...