Netty使用JSSE实现SSLSocket通信

上文讲了netty如何使用openssl生成的签名证书进行加密通信,结果客户端告诉我他们用的netty版本没有SslContextBuilder类,并且由于一些PY交易的原因还不能更新netty....
994b6f2egy1fdr67j7boej20c80d274u.jpg

SslContextBuilder没有java你总有吧,来吧。

一、老规矩,创建key

1.创建客户端和服务端的keystore文件

随便找个文件夹就行,打开命令行输入

keytool -genkey -alias sslserver -keystore sslserverkeys
keytool -genkey -alias sslclient -keystore sslclientkeys
2.将keystore导出证书格式
keytool -export -alias sslserver -keystore sslserverkeys -file sslserver.cer
keytool -export -alias sslclient -keystore sslclientkeys -file sslclient.cer
3.将客户端证书导入到服务器端信任的 keystore 里,将服务器端证书导入到客户端信任的 keystore 里。
keytool -import -alias sslclient -keystore sslservertrust -file sslclient.cer
keytool -import -alias sslserver -keystore sslclienttrust -file sslserver.cer

最后得到有用的文件分别为
服务端:sslserverkeys、sslservertrust
客户端:sslclientkeys、sslclienttrust

二、服务器端代码 (git)

服务器key工厂类 SecureChatSslContextFactory.java
public class SecureChatSslContextFactory {
    private static final String PROTOCOL = "SSL";
    private static final SSLContext SERVER_CONTEXT;
    private static String SERVER_KEY_STORE = ".\\ssl\\sslserverkeys";
    private static String SERVER_TRUST_KEY_STORE = ".\\ssl\\sslservertrust";
    private static String SERVER_KEY_STORE_PASSWORD = "123123123";
    private static String SERVER_TRUST_KEY_STORE_PASSWORD = "123123123";

    static {
        String algorithm = SystemPropertyUtil.get("ssl.KeyManagerFactory.algorithm");
        if (algorithm == null) {
            algorithm = "SunX509";
        }
        SSLContext serverContext;
        try {
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream(SERVER_KEY_STORE), SERVER_KEY_STORE_PASSWORD.toCharArray());
            KeyStore tks = KeyStore.getInstance("JKS");
            tks.load(new FileInputStream(SERVER_TRUST_KEY_STORE), SERVER_TRUST_KEY_STORE_PASSWORD.toCharArray());
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            kmf.init(ks, SERVER_KEY_STORE_PASSWORD.toCharArray());
            tmf.init(tks);
            serverContext = SSLContext.getInstance(PROTOCOL);
            serverContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        } catch (Exception e) {
            throw new Error(e);
        }
        SERVER_CONTEXT = serverContext;
    }
    public static SSLContext getServerContext() {
        return SERVER_CONTEXT;
    }
}
Main.java
public class Main {
    private static final int m_port = 23333;
    public void run() throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new Initializer());
            System.out.println("启动了,端口:" + m_port);
            ChannelFuture f = b.bind(m_port).sync();
            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
            System.out.println("关闭了");
        }
    }
    public static void main(String[] args) throws Exception {
        new Main().run();
    }
}
Initializer.java
public class Initializer extends ChannelInitializer<SocketChannel> {
    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
        engine.setUseClientMode(false);
        engine.setNeedClientAuth(true);
        pipeline.addLast("ssl", new SslHandler(engine));
        pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        pipeline.addLast(new StringDecoder());
        pipeline.addLast(new StringEncoder());
        pipeline.addLast(new Handler());
    }
}
Handler.java
public class Handler extends SimpleChannelInboundHandler<String> {
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        ctx.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 加入\n");
    }
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
        Channel incoming = ctx.channel();
        System.out.println("收到" + incoming.id() + "消息:" + s);
    }
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
       Channel incoming = ctx.channel();
       System.out.println("SimpleChatClient:" + incoming.remoteAddress() + "在线");
    }
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        ctx.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 离开\n");
    }
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        System.out.println(incoming.remoteAddress() + "掉线");
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        Channel incoming = ctx.channel();
        System.out.println(incoming.remoteAddress() + "异常");
        // 当出现异常就关闭连接
        cause.printStackTrace();
        ctx.close();
    }
}

三、客户端代码(git)

SecureChatSslContextFactory.java
public class SecureChatSslContextFactory {
    private static final String PROTOCOL = "SSL";
    private static final SSLContext CLIENT_CONTEXT;
    private static String CLIENT_KEY_STORE = ".\\ssl\\sslclientkeys";
    private static String CLIENT_TRUST_KEY_STORE = ".\\ssl\\sslclienttrust";
    private static String CLIENT_KEY_STORE_PASSWORD = "321321321";
    private static String CLIENT_TRUST_KEY_STORE_PASSWORD = "321321321";
    static {
        String algorithm = SystemPropertyUtil.get("ssl.KeyManagerFactory.algorithm");
        if (algorithm == null) {
            algorithm = "SunX509";
        }
        SSLContext clientContext;
        try {
            KeyStore ks2 = KeyStore.getInstance("JKS");
            ks2.load(new FileInputStream(CLIENT_KEY_STORE), CLIENT_KEY_STORE_PASSWORD.toCharArray());
            KeyStore tks2 = KeyStore.getInstance("JKS");
            tks2.load(new FileInputStream(CLIENT_TRUST_KEY_STORE), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());
            KeyManagerFactory kmf2 = KeyManagerFactory.getInstance(algorithm);
            TrustManagerFactory tmf2 = TrustManagerFactory.getInstance("SunX509");
            kmf2.init(ks2, CLIENT_KEY_STORE_PASSWORD.toCharArray());
            tmf2.init(tks2);
            clientContext = SSLContext.getInstance(PROTOCOL);
            clientContext.init(kmf2.getKeyManagers(), tmf2.getTrustManagers(), null);
        } catch (Exception e) {
            throw new Error(e);
        }
        CLIENT_CONTEXT = clientContext;
    }
    public static SSLContext getClientContext() {
        return CLIENT_CONTEXT;
    }
Main.java
public class Main {
    private static String m_host = "127.0.0.1";
    private static int m_prot = 23333;
    public static void main(String[] args) throws Exception {
        new Main().run();
    }
    public void run() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap bt = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new Initializer());
            Channel channel = bt.connect(m_host, m_prot).sync().channel();
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            while (true) {
                channel.writeAndFlush(in.readLine() + "\r\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
    }
}
Initializer.java
public class Initializer extends ChannelInitializer<SocketChannel>{
    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        SSLEngine engine = SecureChatSslContextFactory.getClientContext().createSSLEngine();
        engine.setUseClientMode(true);
        pipeline.addLast("ssl", new SslHandler(engine));
        pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        pipeline.addLast(new StringDecoder());
        pipeline.addLast(new StringEncoder());
        pipeline.addLast(new Handler());
    }
}
Handler.java
public class Handler extends SimpleChannelInboundHandler<String>{
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
        System.out.println("收到:" + s);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值