netty 集成 wss 安全链接
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 安全链接的更多相关文章
- netty集成ssl完整参考指南(含完整源码)
虽然我们在内部rpc通信中使用的是基于认证和报文头加密的方式实现安全性,但是有些时候仍然需要使用SSL加密,可能是因为对接的三方系统需要,也可能是由于open的考虑.中午特地测了下netty下集成ss ...
- 解决gdal集成libkml的链接错误
作者:朱金灿 来源:http://blog.csdn.net/clever101 gdal库在集成libkml出现一些链接错误: 1>libkmldomD.lib(kml_factory.obj ...
- netty集成springboot
一 前言 springboot 如何集成netty实现mapper调用不为null的问题让好多读者都头疼过,知识追寻者发了一点时间做了个基本入门集成应用给读者们指明条正确的集成方式,我相信,只要你有n ...
- Netty集成Protobuf
一.创建Personproto.proto 创建Personproto.proto文件 syntax = "proto2"; package com.example.protobu ...
- 集成bug统计链接
http://crab.baidu.com/http://bugly.qq.com/ http://bughd.com/ http://www.umeng.com/analyticshttp://tr ...
- netty 的 Google protobuf 开发
根据上一篇博文 Google Protobuf 使用 Java 版 netty 集成 protobuf 的方法非常简单.代码如下: server package protobuf.server.imp ...
- Java项目集成SAP BO
SAP BO报表查看需要登录SAP BO系统,为了方便公司希望将BO报表集成到OA系统中,所以参考网上资料加上与SAP BO的顾问咨询整理出一套通过Java来集成SAP BO的功能. SAPBO中的报 ...
- SpringBoot使用Druid数据库加密链接完整方案
网上的坑 springboot 使用 Druid 数据库加密链接方案,不建议采用网上的一篇文章<springboot 结合 Druid 加密数据库密码遇到的坑!>介绍的方式来进行加密链接实 ...
- nginx lua集成kafka
NGINX lua集成kafka 第一步:进入opresty目录 [root@node03 openresty]# cd /export/servers/openresty/ [root@node03 ...
随机推荐
- 用户禁止cookie后,如何继续使用session
(1)如果用户禁止cookie,服务器仍会将sessionId以cookie的方式发送给浏览器,但是,浏览器不再保存这个cookie(即sessionId)了. (2)如果想继续使用session,需 ...
- 微信小程序中使用iconfont/font-awesome等自定义字体图标
小程序不能识别外部字体文件,但是转换成Base64就可以使用字体图标了. 以阿里巴巴的iconfont为例 1.下载图标 先去官网下载喜欢的图标==> 下载解压后的文件夹==> 2.在线转 ...
- [java,2018-02-01] quartz定时任务中时间表达式
格式: [秒] [分] [小时] [日] [月] [周] [年] 序号 说明 是否必填 允许填写的值 允许的通配符 1 秒 是 ...
- vim basic
1.基本用法 1.1.编辑模式 1.2.底行模式 1.3.环境配置 1.4.使用时发现的 2.编辑多个文档 3.选项 1.基本用法 1.1.编辑模式 插入 插入命令 插入位置 i 光标左侧 a 光标右 ...
- 使用jQuery编辑删除页面内容,两种方式
第一种,比较少的编辑用这种,直接在那块内容上编辑,失去焦点即完成 前几天做编辑框的时候,需要只修改一个状态 //编辑角色 function editTr($this){ thatTd=$($this) ...
- couchdb
http://docs.couchdb.org/en/2.0.0/api/database/find.html#find-selectors
- ERROR 1290 (HY000): The MySQL server is running with the --skip-grant-tables option so it cannot exe
在Mysql集群中创建用户时.出现如下错误! mysql> create user 'testuse'@'localhost' identified by '111111'; ERROR 129 ...
- Ruby学习笔记5: 动态web app的建立 (2)
上一节里,我们搭建了一个数据库的结构,并用index验证了request-response cycle,如下图: 1. Add show method into Controller 这一节,我们要继 ...
- srbac配置
Yii框架中安装srbac扩展方法 以前自己安装过一次srbac,遇到很多问题,虽然都解决了,可是一时偷懒,没做记录. 再次安装时,还是遇到了点麻烦,所以这一还是记下来,以备不时之需. 首先,下载sr ...
- Linq的常见查询
首先定义几个模型类: /// <summary> /// 员工类 /// </summary> public class Employee { /// <summary& ...