平台是 linux,使用 select 函数来进行 IO 复用
对于每一个已连接的描述符,会有一个缓冲区来存储其发送过来的数据。(存储数据的逻辑在文尾)
由于是来多少数据就往缓冲区里存多少数据,这样如果有两个及以上的报文同时进了缓冲区,需要对他们进行分割。
我打算是先以两个\r\n 来进行分割,取出缓冲区里的第一个报文头,如果报文头里有 Content-Length 字段,就继续从缓冲区里读相应长度的数据。
然后就遇到了问题,假如 Content-Length 是伪造的,数值大于实际发送过来的数据的长度,那么会读到下一个报文的报文。
所以想问一下各位有什么解决办法吗
1
leaflxh OP |
2
zzzbkl 2019-08-07 12:08:58 +08:00 via Android
rfc 里面描述 content-length 时用的是 should 而不是 must,通过它来验证长度确实不靠谱。同好奇
|
3
009694 2019-08-07 12:21:29 +08:00 via iPhone
content-length 是用来验证报文完整性而不是用来听之任之长度读取的吧。。
|
4
abcbuzhiming 2019-08-07 12:38:30 +08:00 1
楼主,我觉得你的思路不对,首先 Http 是基于 TCP 的,每个连接的缓冲区都是独立的,现在假设有一个有恶意的人,伪造了 Content-Length,把它变的更长,那么就算你读下去,你读到的仍然是这个人后续发来的包,你就把后续得到的包数据也当成是 request body 的内容好了。这有什么问题呢,你是告诉我有这么长的,我就读这么长,我看过 Nginx 的实现,只有在读到不够长度的数据时才会报错断开连接,但是只要后续能继续读到数据,就会继续读下去,http 的 content-length 就是 body 长度指示器,只要它不超过 http 协议定义的最大长度,你就照着读,没错的
|
5
ipwx 2019-08-07 12:40:18 +08:00 via Android
@abcbuzhiming 我觉得楼主可能担心客户端伪造了超长 content length
|
7
des 2019-08-07 12:49:22 +08:00 via Android
补充一点,仅仅两个\r\n 来进行分割,也是考虑不完全的,因为有可能对方不发这个,然后就挂了
|
8
abcbuzhiming 2019-08-07 14:00:12 +08:00
@ipwx 超长的 content length 可以被 http 服务器的最大包长参数限制,主流的 http 服务器实现都带有这个参数,一旦超了直接 close socket
|
9
walkman660 2019-08-07 15:16:57 +08:00
觉得楼主可以试下在已有开源的 HTTP SERVER 做修改满足需求
自己写一边太麻烦了 |
10
leaflxh OP 🌚决定直接关闭连接,因为请求者发送的数据长度扰乱了本次连接的缓冲区管理
|
11
julyclyde 2019-08-07 16:06:53 +08:00
首先 HTTP 是基于 TCP 的
TCP 不是报文,而是流 只有坚信流式思维才能想明白这个问题 |
12
tabris17 2019-08-07 16:10:52 +08:00
根据 content-length 来截断数据包这个思路本身就有问题吧
|
13
momocraft 2019-08-30 15:09:28 +08:00
content-length 是用户传的(而且和其他请求一样是可以随便造的)。服务器能处理正确情况,并在出错时继续稳定运行就可。
|