netty集成ssl完整参考指南(含完整源码)

虽然我们在内部rpc通信中使用的是基于认证和报文头加密的方式实现安全性,但是有些时候仍然需要使用SSL加密,可能是因为对接的三方系统需要,也可能是由于open的考虑。中午特地测了下netty下集成ssl的功能,关于ssl的握手过程以及java安全框架中的相关组件说明,请参考如下链接:

http://www.cnblogs.com/zhjh256/p/6262620.html

http://www.cnblogs.com/zhjh256/p/6104537.html

网上搜了下,并没有看到完整的netty ssl示例例子,netty in action中也只是匆匆带过。特详细的测试和整理如下。

首先生成服务端证书:

D:\security\server>keytool -genkey -alias securechat -keysize 2048 -validity 365 -keyalg RSA -dname "CN=localhost" -keypass sNetty -storepass sNetty -keystore sChat.jks

D:\security\server>keytool -export -alias securechat -keystore sChat.jks -storepass sNetty -file sChat.cer
存储在文件 <sChat.cer> 中的证书

D:\security\server>cd /d ../client

D:\security\client>keytool -genkey -alias smcc -keysize 2048 -validity 365 -keyalg RSA -dname "CN=localhost" -keypass cNetty -storepass cNetty -keystore cChat.jks

D:\security\client>keytool -import -trustcacerts -alias securechat -file ../server\sChat.cer -storepass cNetty -keystore cChat.jks
所有者: CN=localhost
发布者: CN=localhost
序列号: 78384348
有效期开始日期: Wed Mar 01 12:48:48 CST 2017, 截止日期: Thu Mar 01 12:48:48 CST 2018
证书指纹:
MD5: 94:83:6C:6D:4B:0D:0B:E6:BF:39:B7:2C:17:29:E8:3C
SHA1: 9A:29:27:41:BE:71:38:C8:13:99:3A:8F:C6:37:C2:95:31:14:B4:98
SHA256: E9:31:40:C7:FC:EA:EF:24:54:EF:4C:59:50:44:CB:1F:9A:35:B7:26:07:2D:3B:1F:BC:30:8E:C0:63:45:4F:21
签名算法名称: SHA256withRSA
版本: 3

扩展:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 9B 96 0D 50 4A 5E AF 3D 56 25 9C A5 69 C1 3E CC ...PJ^.=V%..i.>.
0010: 32 85 0D A8 2...
]
]

是否信任此证书? [否]: 是
证书已添加到密钥库中

netty服务端源码:

package com.ld.net.spider.server;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import java.net.InetSocketAddress; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class SpiderServerBusiHandler extends SimpleChannelInboundHandler<Object> {
static final Logger logger = LoggerFactory.getLogger(SpiderServerBusiHandler.class); @Override
protected void channelRead0(final ChannelHandlerContext ctx, final Object msg)
throws Exception {
System.out.println(msg.toString());
} @Override
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause) throws Exception {
logger.error("channel " + ((InetSocketAddress)ctx.channel().remoteAddress()).toString() + " exception:",cause);
ctx.close();
}
}
package com.ld.net.spider.channel;

import java.nio.charset.Charset;

import javax.net.ssl.SSLEngine;

import com.ld.net.spider.server.SpiderServerBusiHandler;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslHandler; public class SslChannelInitializer extends ChannelInitializer<Channel> {
private final SslContext context; public SslChannelInitializer(SslContext context) {
this.context = context;
} @Override
protected void initChannel(Channel ch) throws Exception {
SSLEngine engine = context.newEngine(ch.alloc());
engine.setUseClientMode(false);
ch.pipeline().addFirst("ssl", new SslHandler(engine));
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4)); //最大16M
pipeline.addLast("decoder", new StringDecoder(Charset.forName("UTF-8")));
pipeline.addLast("encoder", new StringEncoder(Charset.forName("UTF-8")));
pipeline.addLast("spiderServerBusiHandler", new SpiderServerBusiHandler());
}
}
package com.ld.net.spider.channel;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder; import java.io.FileInputStream;
import java.security.KeyStore; import javax.net.ssl.KeyManagerFactory; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class SocketServerHelper {
static final Logger logger = LoggerFactory.getLogger(SocketServerHelper.class);
private static int WORKER_GROUP_SIZE = Runtime.getRuntime().availableProcessors() * 2; private static EventLoopGroup bossGroup;
private static EventLoopGroup workerGroup; private static Class<? extends ServerChannel> channelClass; public static void startSpiderServer() throws Exception {
ServerBootstrap b = new ServerBootstrap();
b.childOption(ChannelOption.TCP_NODELAY, true)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.SO_REUSEADDR, true)
.childOption(ChannelOption.ALLOCATOR, new PooledByteBufAllocator(false))
.childOption(ChannelOption.SO_RCVBUF, 1048576)
.childOption(ChannelOption.SO_SNDBUF, 1048576); bossGroup = new NioEventLoopGroup(1);
workerGroup = new NioEventLoopGroup(WORKER_GROUP_SIZE);
channelClass = NioServerSocketChannel.class;
logger.info("workerGroup size:" + WORKER_GROUP_SIZE);
logger.info("preparing to start spider server...");
b.group(bossGroup, workerGroup);
b.channel(channelClass);
KeyManagerFactory keyManagerFactory = null;
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream("D:\\security\\server\\sChat.jks"), "sNetty".toCharArray());
keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore,"sNetty".toCharArray());
SslContext sslContext = SslContextBuilder.forServer(keyManagerFactory).build();
b.childHandler(new SslChannelInitializer(sslContext));
b.bind(9912).sync();
logger.info("spider server start sucess, listening on port " + 9912 + ".");
} public static void main(String[] args) throws Exception {
SocketServerHelper.startSpiderServer();
} public static void shutdown() {
logger.debug("preparing to shutdown spider server...");
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
logger.debug("spider server is shutdown.");
}
}
package com.ld.net.spider.channel;

import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture; public class SocketHelper {
static final Logger logger = LoggerFactory.getLogger(SocketHelper.class); public static ChannelFuture writeMessage(Channel channel,String msg) {
if(channel!=null){
try {
return channel.writeAndFlush(msg).sync();
} catch (Exception e) {
String otherInfo = ""; if(channel.remoteAddress() != null) {
otherInfo = "remote address [" + ((InetSocketAddress)channel.remoteAddress()).toString() + "]";
} else {
otherInfo = "channel is null.";
} if(e instanceof ClosedChannelException) {
logger.error("channel to " + otherInfo + " is closed",e);
} else {
logger.error("timeout occured during channel send msg, " + otherInfo,e);
}
}
}else{
logger.error("send msg failed, channel is disconnected or not connect. channel is null, please see caller log.");
}
return null;
} public static ChannelFuture writeMessage(Channel channel,ByteBuf msg) {
if(channel!=null){
try {
return channel.writeAndFlush(msg).sync();
} catch (Exception e) {
logger.error("timeout occured during channel send msg. remote address is:" + ((InetSocketAddress)channel.remoteAddress()).toString(),e);
}
}else{
logger.error("send msg failed, channel is disconnected or not connect, channel is null, please see caller log.");
}
return null;
}
}

netty 集成 wss 安全链接的更多相关文章

  1. netty集成ssl完整参考指南(含完整源码)

    虽然我们在内部rpc通信中使用的是基于认证和报文头加密的方式实现安全性,但是有些时候仍然需要使用SSL加密,可能是因为对接的三方系统需要,也可能是由于open的考虑.中午特地测了下netty下集成ss ...

  2. 解决gdal集成libkml的链接错误

    作者:朱金灿 来源:http://blog.csdn.net/clever101 gdal库在集成libkml出现一些链接错误: 1>libkmldomD.lib(kml_factory.obj ...

  3. netty集成springboot

    一 前言 springboot 如何集成netty实现mapper调用不为null的问题让好多读者都头疼过,知识追寻者发了一点时间做了个基本入门集成应用给读者们指明条正确的集成方式,我相信,只要你有n ...

  4. Netty集成Protobuf

    一.创建Personproto.proto 创建Personproto.proto文件 syntax = "proto2"; package com.example.protobu ...

  5. 集成bug统计链接

    http://crab.baidu.com/http://bugly.qq.com/ http://bughd.com/ http://www.umeng.com/analyticshttp://tr ...

  6. netty 的 Google protobuf 开发

    根据上一篇博文 Google Protobuf 使用 Java 版 netty 集成 protobuf 的方法非常简单.代码如下: server package protobuf.server.imp ...

  7. Java项目集成SAP BO

    SAP BO报表查看需要登录SAP BO系统,为了方便公司希望将BO报表集成到OA系统中,所以参考网上资料加上与SAP BO的顾问咨询整理出一套通过Java来集成SAP BO的功能. SAPBO中的报 ...

  8. SpringBoot使用Druid数据库加密链接完整方案

    网上的坑 springboot 使用 Druid 数据库加密链接方案,不建议采用网上的一篇文章<springboot 结合 Druid 加密数据库密码遇到的坑!>介绍的方式来进行加密链接实 ...

  9. nginx lua集成kafka

    NGINX lua集成kafka 第一步:进入opresty目录 [root@node03 openresty]# cd /export/servers/openresty/ [root@node03 ...

随机推荐

  1. 测试oracle数据库连接

    1.ping 192.168.0.12.telnet 192.168.0.1 1521 按下ctrl+] 组合键出现命令回显才是端口连接成 3.tnsping 192.168.0.1:1521/db

  2. python import问题

    python中包:一个文件夹中必须要有__init__.py文件,才能被识别为 包,才能被其他模块引入python中 模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path ...

  3. Java8 list根据对象某个属性去重

    1. 添加方法: import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import j ...

  4. 深入Spring Boot:怎样排查 Cannot determine embedded database driver class for database type NONE

    ref:https://www.journaldev.com/13830/spring-boot-cannot-determine-embedded-database-driver-class-for ...

  5. 关于transition和animation

    最近的工作以移动端项目居多,经常会涉及一些比较小的动画效果,所以使用css3设计动画效果也就越发熟练起来.但是不得不承认,一直以来都是凭感觉使用transform, transition, anima ...

  6. 零基础学习python_类和对象(36-40课)

    今天我们开始学习面向对象的知识咯,之前我对面向对象也学的懵懵的,因为感觉知道好像又不是特别清楚,接下来我们一起来学习类和对象吧.零基础的课程我都是看小甲鱼的视频学的,没基础的可以去这个网址下载视频学习 ...

  7. for循环案例

    for循环案例 今天给大家介绍点for循环的案例 1.大马驮2石粮食,中马驮1石粮食,两头小马驮一石粮食,要用100匹马,驮100石粮食,该如何调配? <!DOCTYPE html> &l ...

  8. CMake实践--操作

    ---<Cmake 实践>--- ---Ubuntu 14.04 1.创建一个cmake文件目录 mkdir -p ~/cmake 2.在cmake文件下创建t1子目录 cd ~/cmak ...

  9. 58.纯 CSS 创作一只卡通鹦鹉

    原文地址:https://segmentfault.com/a/1190000015339977 优化后效果地址:https://scrimba.com/c/c97Z2vuD 感想:消除了图片外的:h ...

  10. 《算法》第三章部分程序 part 3

    ▶ 书中第三章部分程序,加上自己补充的代码,红黑树 ● 红黑树,大部分方法与注释与二叉树相同 package package01; import java.util.NoSuchElementExce ...