netty 实现https服务器

0 概述

netty 通过JDK的SSLEngine,以SslHandler的方式提供对SSL/TLS 安全传输的支持,极大的简化了开发工作。本文主要讲述如何使用netty实现简单的https服务器。

1 SSL单向认证

所谓的单向认证,即客户端只验证服务端的合法性,服务端不会验证客户端。
单向认证过程的总结如下:
1.SSL客户端(浏览器)向服务端传送客户端 SSL协议的版本号、支持的加密算法种类、产生的随机数,以及其他可选信息。
2.服务端返回握手应答,向客户端传送确认SSL协议的版本号、加密算法种类、随机数以及其他信息。
3.服务端向客户端发送自己的证书,这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等
4.客户端对服务端的证书进行认证,服务端的合法性校验包括:证书是否过期、发行服务器证书CA是否可靠、发行者证书的公钥能否解开服务器证书的“发行者数字签名”等
5.客户端随机产生一个用于后续通信的对称密钥,然后用服务端的公钥加密传输给服务端,通知服务端客户端的握手结束。
6.服务端解密获取客户端的对称密钥,同时通知客户端服务端的握手结束。
7.SSL的握手部分结束,SSL安全通道建立,客户端和服务端开始使用相同的对称密钥对数据进行加密,然后通过socket进行传输。

2 具体实现

   <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.15.Final</version>
        </dependency>

利用JDK的keytool 工具,生成服务端私钥和证书仓库。
执行如下命令:
keytool -genkey -keysize 2048 -validity 365 -keyalg RSA -dname “CN=localhost” -keypass hsc123 -storepass hsc123 -keystore local.jks

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.ssl.SslHandler;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;

/**
 * Created by apple on 17/10/21.
 */
public class HttpsServer {

    public static void start(final int port) throws Exception {
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        try {
            serverBootstrap.channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .group(boss, worker)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            SSLEngine sslEngine = SSLContextFactory.getSslContext().createSSLEngine();
                            sslEngine.setUseClientMode(false);
                            ch.pipeline().addLast(new SslHandler(sslEngine));
                            ch.pipeline().addLast("http-decoder", new HttpServerCodec());
                            ch.pipeline().addLast(new HttpsSeverHandler());
                        }
                    });
            ChannelFuture future = serverBootstrap.bind(port).sync();
            future.channel().closeFuture().sync();
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }

    }

    public static void main(String[] args) throws Exception {
        start(7000);
    }

}
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;

/**
 * Created by apple on 17/10/21.
 */
public class SSLContextFactory {

    public static SSLContext getSslContext() throws Exception {
        char[] passArray = "hsc123".toCharArray();
        SSLContext sslContext = SSLContext.getInstance("TLSv1");
        KeyStore ks = KeyStore.getInstance("JKS");
        //加载keytool 生成的文件
        FileInputStream inputStream = new FileInputStream("/Users/apple/local.jks");
        ks.load(inputStream, passArray);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, passArray);
        sslContext.init(kmf.getKeyManagers(), null, null);
        inputStream.close();
        return sslContext;

    }
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.*;

/**
 * Created by apple on 17/10/21.
 */
public class HttpsSeverHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HttpRequest) {
            HttpRequest request = (HttpRequest) msg;
            boolean keepaLive = HttpUtil.isKeepAlive(request);
            System.out.println("method" + request.method());
            System.out.println("uri" + request.uri());
            FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
            httpResponse.content().writeBytes("https".getBytes());
            httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=UTF-8");
            httpResponse.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, httpResponse.content().readableBytes());
            if (keepaLive) {
                httpResponse.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
                ctx.writeAndFlush(httpResponse);
            } else {
                ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
            }
        }
    }
}

3 测试

启动服务 输入https://127.0.0.1:7000

这里写图片描述
参考文献
[1] Netty 权威指南(第二版),李林峰著

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Netty是一个异步非阻塞的事件驱动型的网络应用程序框架,可以用于实现Socket。Socket是计算机网络中运输层的TCP协议的抽象,用于实现不同应用程序进程或网络连接之间的通信。在Netty中,我们可以使用其提供的API进行网络编程,包括建立Socket连接、读写数据等操作。Netty框架简化了网络编程的复杂性,提供了高性能、方便开发的NIO(非阻塞IO)解决方案,可以用于快速开发高性能的协议服务器和客户端。所以,Netty可以实现Socket编程,并且是一个被广泛使用的网络应用程序框架。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Netty进行Socket编程(一)](https://blog.csdn.net/Solo_two/article/details/78394823)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [spring boot 整合的netty 实现的socket的服务端和客户端](https://download.csdn.net/download/qq_28898309/11166535)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值