如何让 netty 同时支持HTTP与HTTPS

在netty 中添加自带的 SslHandler 就能支持HTTPS,但是添加之后使用 HTTP 访问是存在问题的。
请问如何能支持使用用一个端口两种协议并行,比如在某个事件中判断出使用 HTTPS 协议然后在把 SslHandler 添加到 pipeline 中。

SelfSignedCertificate ssc = new SelfSignedCertificate();
SslContext sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
SSLEngine sslEngine = sslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT);
ch.pipeline().addFirst( new SslHandler(sslEngine));
阅读 8k
2 个回答

让同一个端口监听两种不同的协议,这本身是一个不好的设计,一般80端口提供HTTP协议,443端口提供HTTPS协议。不过Netty已经提供了同一个端口支持SSLnon-SSL的工具类OptionalSslHandler
参考一下:https://github.com/netty/nett...

根据 node如何让一个端口同时支持https与http 文中描述的https数据流的第一位是十六进制“16”,转换成十进制就是22,在读取的第一位数据进行判断实现动态添加 ChannelHandler 。

.childHandler(new ChannelInitializer<NioSocketChannel>() {
    protected void initChannel(final NioSocketChannel ch) throws Exception {
        ch.pipeline().addFirst(new ChannelInboundHandlerAdapter() {
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                if (((ByteBuf) msg).getByte(0) == 22) {
                    SelfSignedCertificate ssc = new SelfSignedCertificate();
                    SslContext sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
                    SSLEngine sslEngine = sslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT);
                    // 将处理 https 的处理程序添加至 HttpServerCodec 之前
                    ctx.pipeline().addBefore("HttpServerCodec", "sslHandler", new SslHandler(sslEngine));
                }
                ctx.pipeline().remove(this);
                super.channelRead(ctx, msg);
            }
        });

        ch.pipeline().addLast("HttpServerCodec", new HttpServerCodec());
        ch.pipeline().addLast("aggregator", new HttpObjectAggregator(10 * 1024 * 1024));
        ch.pipeline().addLast(new HttpServerHandler());
    }
});

反之先添加 sslHandler 在移除也行

.childHandler(new ChannelInitializer<NioSocketChannel>() {
    protected void initChannel(final NioSocketChannel ch) throws Exception {
        ch.pipeline().addFirst(new ChannelInboundHandlerAdapter() {
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                if (((ByteBuf) msg).getByte(0) != 22) {
                    // 删除 sslHandler
                    ctx.pipeline().remove("sslHandler");
                }
                ctx.pipeline().remove(this);
                super.channelRead(ctx, msg);
            }
        });

        SelfSignedCertificate ssc = new SelfSignedCertificate();
        SslContext sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
        SSLEngine sslEngine = sslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT);
        ch.pipeline().addLast( "sslHandler", new SslHandler(sslEngine));
        ch.pipeline().addLast("HttpServerCodec", new HttpServerCodec());
        ch.pipeline().addLast("aggregator", new HttpObjectAggregator(10 * 1024 * 1024));
        ch.pipeline().addLast(new HttpServerHandler());
    }
});
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题