基于NIO的的HTTPS的实现

        在特定场景下,应用不需要一个很庞大的WEB框架,而是只需要一个很小概念范围的接口。

        当使用WEB框架时,需要能够承受该框架本身漏洞所带来的风险,所以希望通过自行代码实现一个简单的WEB框架。

        首先基于TCPServer,能够接收来源于客户端的数据,而后书写一个HTTP的解析器,首先通过双换行分割HTTP的头部,而后通过头部的长度信息或者其它标识,获得完整的HTTP数据体部分,再行数据的分析,得到WEB框架常用的键值模式或者文件模式等。

        一个简单的TCPServer代码:

this.serverSocket = ServerSocketChannel.open();
this.serverSocket.configureBlocking(false);
this.serverSocket.socket().bind(new InetSocketAddress(this.ip,this.port),10000);

        而后开启一个AcceptSelector(Selector.open())和多个ReadSelector进行数据的读取,能够接收Socket连接以及当Socket中有数据时,能够触发通知应用进行数据读取的流程。

        下面是一个HTTP数据的原始样本。

POST /index.html HTTP/1.1
User-Agent: PostmanRuntime/7.37.3
Accept: */*
Postman-Token: 1333908a-a6c6-41fc-8433-9e4126f7d0d2
Host: 127.0.0.1:8080
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 19

K1=V1&K2=%E5%80%BC2

        所以书写HTTP服务器,关键在于书写HTTP的头部和数据部的解析,同时考虑大数据量的情况下,能够借助磁盘缓存达到数据缓存的目的,同时对不同的传输方式,能够支持,如chunked传输等。

        本章主要描述的是在该基础上,如何附加实现HTTPS的服务器。

        使用SSLContext创建SSLEngine,为每个TCP连接创建。

KeyStore keyStore = KeyStore.getInstance("JKS");
jksFile = new File(this.getStringPara("jks"));
if (!jksFile.isFile()) {
		this.error("no jks file. " + this.getStringPara("jks"));
		return null;
}

String pwd = this.getStringPara("jks_pwd");
in = new FileInputStream(jksFile);
keyStore.load(in, pwd == null ? null : pwd.toCharArray());

// Create key manager
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, pwd == null ? null : pwd.toCharArray());
KeyManager[] km = keyManagerFactory.getKeyManagers();

// Create trust manager
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
trustManagerFactory.init(keyStore);
TrustManager[] tm = trustManagerFactory.getTrustManagers();

// Initialize SSLContext
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(km, tm, null);

在连接创建时,调用如下代码创建SSLEngine
SSLEngine engine = this.sslContext.createSSLEngine();
engine.setUseClientMode(false);

        而后结合engine的状态,分为NOT_HANDSHAKING、NEED_WRAP、NEED_UNWRAP、FINISHED,建议连接刚建立时就调用beginHandshake,这样能确保出现NOT_HANDSHAKING和FINISHED时,都代表握手已经完成,当进入NEED_UNWRAP时,需要从等待网络数据来源,调用engine的unwrap方法,而当NEED_WRAP时,需要进行进行wrap动作,并把数据发送给对端。

        一旦engine进入NOT_HANDSHAKING和FINISHED时,意味着握手已经完成,unwrap(解密)数据即为http的数据,按照原http流程进行解析即可,而当发送数据时,需要把发送的数据进行wrap(加密)后再行发送。

        如此,在NIO TCPServer的基础上,实现了HTTP,增加SSLEngine后,再支撑了HTTPS,最终得到一个轻量级的HTTPServer,避免了框架级别的漏洞引入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值