生成自签证书
1、生成自签证书
可以参考这篇 使用keytool工具生成证书
关于keytool的官方说明:https://docs.oracle.com/javase/6/docs/technotes/tools/solaris/keytool.html
2、客户端导入证书
对于自签证书 需要在客户端进行导入,导入证书命令如下:
keytool -import -trustcacerts -alias netty -keystore $JAVA_HOME/jre/lib/security/cacerts -file nginx.crt -storepass changeit
例如:
RickydeMBP:netty-in-action apple$ sudo keytool -import -trustcacerts -alias netty -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts -file /var/folders/_y/q3j1y2fn6996rzfd8_50xzjm0000gn/T/keyutil_example.com_2847488297227795850.crt -storepass changeit
会提示 是否信任此证书? 输入 y 即可。控制台输出如下:
所有者: CN=example.com
发布者: CN=example.com
序列号: 9ac1b92fa3e2812
有效期为 Sat Jun 01 10:58:41 CST 2019 至 Sat Jan 01 07:59:59 CST 10000
证书指纹:
MD5: 92:5C:7A:F6:56:F5:04:6C:AF:D3:AD:1D:09:B0:3E:E1
SHA1: 59:29:5E:19:BE:B7:9D:4F:FB:96:0B:5E:A8:F8:7F:1C:19:0F:BB:D3
SHA256: AC:7E:DB:8F:84:16:A5:49:CE:C2:BB:CD:A2:E9:C5:1B:F1:38:C6:9D:FA:51:E6:82:34:FB:66:52:35:9C:53:16
签名算法名称: SHA256withRSA
主体公共密钥算法: 2048 位 RSA 密钥
版本: 3
是否信任此证书? [否]: y
证书已添加到密钥库中
删除:
keytool -delete -alias netty -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
Netty开启SSL
Netty中提供了io.netty.handler.ssl.SslHandler类,使用起来非常便捷。
本文中使用的Netty版本为 4.1.42.Final,不同版本可能略有不同。
Server端
代码如下:
public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
UserAuthHandler userAuthHandler = new UserAuthHandler();
//SSL
SelfSignedCertificate ssc = new SelfSignedCertificate();
System.out.println(ssc.certificate());
System.out.println(ssc.privateKey());
SslContext sslContext = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
.build();
try {
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) // (3)
.handler(new LoggingHandler(LogLevel.INFO)) //增加LOG
.option(ChannelOption.SO_BACKLOG, 128)
.childHandler(new ChannelInitializer<NioSocketChannel>() { // (4)
@Override
public void initChannel(NioSocketChannel ch) throws Exception {
//pipeline
ChannelPipeline pipeline = ch.pipeline();
//增加LOG
pipeline.addLast("loggingHandler", new LoggingHandler(LogLevel.INFO));
//空闲检测
pipeline.addLast("idleCheckHandler", new ServerIdleCheckHandler());
//SSL
SslHandler sslHandler = sslContext.newHandler(ch.alloc());
pipeline.addLast("sslHandler", sslHandler);
//注意:顺序不能错
//handler的顺序:读保证自上而下,写保证自下而上就行了,读与写之间其实顺序无所谓,但是一般为了好看对称,我们是一组一组写。
pipeline.addLast("orderFrameDecoder", new OrderFrameDecoder());
pipeline.addLast("orderFrameEncoder", new OrderFrameEncoder());
pipeline.addLast("orderProtocolEncoder", new OrderProtocolEncoder());
pipeline.addLast("orderProtocolDecoder", new OrderProtocolDecoder());
//用户身份鉴权
pipeline.addLast("userAuthHandler", userAuthHandler);
pipeline.addLast("orderProcessHandler", new OrderServerProcessHandler());
}
});
// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(port).sync(); // (7)
LOG.info("点餐系统-服务端, port:{} 启动完成", port);
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
Client端
代码如下:
public void run() throws Exception {
EventLoopGroup workerGroup = new NioEventLoopGroup();
//SSL
SslContext sslContext = SslContextBuilder.forClient()
.build();
try {
Bootstrap b = new Bootstrap(); // (1)
b.group(workerGroup); // (2)
b.channel(NioSocketChannel.class); // (3)
b.option(ChannelOption.SO_KEEPALIVE, true); // (4)
b.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
//pipeline
ChannelPipeline pipeline = ch.pipeline();
//增加LOG
pipeline.addLast("loggingHandler", new LoggingHandler(LogLevel.INFO));
//SSL
SslHandler sslHandler = sslContext.newHandler(ch.alloc());
pipeline.addLast("sslHandler", sslHandler);
//空闲检测
pipeline.addLast("idleStateHandler", new IdleStateHandler(0, 15, 0, TimeUnit.SECONDS));
//注意:顺序不能错
//handler的顺序:读保证自上而下,写保证自下而上就行了,读与写之间其实顺序无所谓,但是一般为了好看对称,我们是一组一组写。
pipeline.addLast("orderFrameDecoder", new OrderFrameDecoder());
pipeline.addLast("orderFrameEncoder", new OrderFrameEncoder());
pipeline.addLast("orderProtocolEncoder", new OrderProtocolEncoder());
pipeline.addLast("orderProtocolDecoder", new OrderProtocolDecoder());
//心跳检测
pipeline.addLast("keepLiveHandler", new ClientKeepLiveHandler());
//处理响应结果
pipeline.addLast("orderClientHandler", new OrderClientHandler());
}
});
// Start the client.
ChannelFuture f = b.connect(host, port).sync(); // (5)
LOG.info("点餐系统-客户端, 连接服务器:{}:{}", host, port);
//身份鉴权
Command authCommand = new AuthCommand("admin", "admin");
RpcRequest authRequest = new RpcRequest(IdUtils.nextRequestId(), authCommand);
//发送
f.channel().writeAndFlush(authRequest);
//1.发送点餐请求
Long requestId = IdUtils.nextRequestId();
Command command = new OrderCommand(IdUtils.nextSeatId(), Arrays.asList("鱼香肉丝"));
RpcRequest request = new RpcRequest(requestId, command);
//2.写入
f.channel().writeAndFlush(request);
LOG.info("点餐系统-客户端, 向服务器:{}:{} 发送点餐请求requestId:{}, 请求报文:{}",
host, port, requestId, JsonUtils.toJson(request));
//3.等待响应结果
CommandResultFuture future = new CommandResultFuture();
RequestPendingCenter.INSTANCE.add(requestId, future);
//3.1 获取结果
CommandResult result = future.get();
LOG.info("点餐系统-客户端, 收到服务器:{}:{} 请求requestId:{} 响应结果:{}",
host, port, requestId, JsonUtils.toJson(result));
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
}
}
相关资料
生成自签证书
1、生成自签证书
可以参考这篇 使用keytool工具生成证书
关于keytool的官方说明:https://docs.oracle.com/javase/6/docs/technotes/tools/solaris/keytool.html
2、客户端导入证书
对于自签证书 需要在客户端进行导入,导入证书命令如下:
例如:
会提示 是否信任此证书? 输入 y 即可。控制台输出如下:
删除:
Netty开启SSL
Netty中提供了
io.netty.handler.ssl.SslHandler类,使用起来非常便捷。本文中使用的Netty版本为 4.1.42.Final,不同版本可能略有不同。
Server端
代码如下:
Client端
代码如下:
相关资料