-
-
大家好,
今天,我们将向大家介绍我们的CS305-2023Fall项目,该项目的重点是基于HTTP/1.1协议实现一个文件管理服务器。我们的项目旨在创建一个强大而高效的服务器,使客户端能够执行各种文件管理操作,例如查看、下载、上传和删除文件。同时我们为了方便测试以及用户的体验,我们还写了一个html文档以供方便展示。
为了实现我们的目标,我们设计了一个自定义的HTTP服务器框架,并且自主实现了Python中的Socket API(TCPServer.py)。该框架提供了处理传入的HTTP请求、解析请求和生成适当响应的必要功能。它使我们能够构建一个可扩展和可靠的文件管理服务器。
代码使用SQLite数据库连接,分别连接了
users.db
和cookies.db
两个数据库文件。这些数据库用于存储用户信息和会话信息。- 验证 Cookie:函数首先检查请求头部中是否包含
Cookie
字段。如果存在,它将提取出会话 ID,并在cookies.db
数据库中查找相应的会话信息。 - 用户名密码验证:如果未提供 Cookie,函数将检查请求头部中是否包含
Authorization
字段。如果存在,它将提取出用户名和密码,并在users.db
数据库中查找相应的用户信息。 - 会话创建和更新:如果用户名和密码验证成功,函数将生成一个新的会话 ID,并将会话信息插入到
cookies.db
数据库中。会话 ID 通过设置Set-Cookie
响应头部返回给客户端,同时对于一个cookies
,设置他的有效时间为一小时,如果时间超出需要重新返回认证。 - 异常处理:如果验证失败或发生异常,函数将设置
User
字段为None
,并在响应头部中添加WWW-Authenticate
字段,要求进行基本身份验证。
![image-20231216205657542](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216205657542.png)
在我们的框架中,我们使用了几种数据结构来处理和表达HTTP消息的每个部分。主要的数据结构包括:
-
请求(Request):
- 方法(Method):表示请求中使用的HTTP方法(例如GET、POST、DELETE)。
- URL:存储请求的URL。
- 头部(Headers):包含请求中的各种头部信息。
- 主体(Body):存储请求体的内容(如果有)。
![image-20231216203936269](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216203936269.png)
-
响应(Response):
- 状态码(Status code):指示响应的状态(例如200 OK、404 Not Found)。
- 头部:存储要包含在响应中的头部信息。
- 主体:包含响应的内容。
![image-20231216203715567](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216203715567.png)
当服务器接收到一个请求时,我们按照以下流程来处理它:
- 解析:我们解析接收到的请求,提取相关信息,例如请求方法、URL、头部和主体。
- 映射:我们将请求目标(URL)映射到服务器中相应的函数。这使我们能够确定所请求资源的适当操作。
- 执行:映射完成后,我们执行相应的服务器函数来处理请求。这可能涉及任务,如提供目录列表、处理文件下载、处理文件上传或删除文件。
- 生成响应:在执行服务器函数之后,我们根据请求的结果生成响应。响应包括适当的状态码、头部和响应主体(如果需要)。
![image-20231216204202617](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216204202617.png)
在我们的项目的基本部分中,我们成功实现了以下组件:
-
基本HTTP服务器:我们使用Python的Socket API构建了一个HTTP服务器,用于处理传入的请求。服务器能够按照HTTP/1.1协议解析和生成响应。
-
目录列表:我们的服务器提供目录列表功能,允许客户端查看目录的内容。当客户端向目录发送GET请求时,服务器会生成一个HTML响应,列出所有的文件和子目录。
-
文件下载:客户端可以通过向文件的URL发送GET请求来从服务器下载文件。服务器会读取请求的文件,并将其内容作为响应主体返回。
![image-20231216210318742](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216210318742.png)
-
文件上传:客户端可以通过发送带有文件作为请求主体的POST请求将文件上传到服务器。服务器会处理文件上传,将文件保存到适当的位置,并返回指示上传过程成功或失败的响应。
![image-20231216210343775](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216210343775.png)
-
文件删除:客户端可以通过向文件的URL发送DELETE请求来从服务器删除文件。服务器会处理删除过程,从服务器的存储中删除请求的文件,并返回指示删除过程成功或失败的响应。
![image-20231216210358650](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216210358650.png)
![image-20231216210610508](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216210610508.png)
按照1024字节为一个单位,然后配上16进制表示的长度和封装发送。
为了说明头部的使用和HTTP消息主体的内容,让我们通过Wireshark查看一些示例:
- GET请求:
![image-20231216211533377](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216211533377.png)
![image-20231216211504884](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216211504884.png)
- POST请求:
![image-20231216211710058](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216211710058.png)
![image-20231216211653420](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216211653420.png)
- DELETE请求:
![image-20231216211737348](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216211737348.png)
![image-20231216211247426](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216211247426.png)
![image-20231216210644270](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216210644270.png)
单个文件和多个文件的切片传输需要分别处理,分别设置不同的Content-Type包括request header的内容
![image-20231216212826906](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216212826906.png)
![image-20231216213009190](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216213009190.png)
![image-20231216232643042](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216232643042.png)
![image-20231216232726987](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216232726987.png)
加密的具体流程为:
- Client 发起连接,接收到Server端生成的RSA公钥
- Client 生成AES密钥,并用接收到的公钥加密密钥
- Client 发送密文给 Server端,Server用自己的私钥解密,得到
key
- 双方通过AES对称密钥通信,其中初始向量为硬编码的
iv
(约定俗成)
加密后的流量如上图所示,第一段明文
PEM
格式的RSA公钥,随后的数据传输皆为密文形式。![image-20231216213313545](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216213313545.png)
在传输大文件的时候,使用chunked Transfer,不需要等文件完全读取成功之后统一发送,而是以1024个字节为一个单位,封装后发送,节省了时间。
美观简约的交互界面,可以支持上传下载删除包括最开始的认证,以及返回根目录、上级目录,访问文件夹和显示当前目录的功能
![image-20231216213509403](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216213509403.png)
![image-20231216213730824](/Users/serendipity/Library/Application Support/typora-user-images/image-20231216213730824.png)
以及相应的HTML文件(index.html)
完善的异常处理,包括信息的认证,命令的格式,以及上传下载文件的存在性检查等
通过这个项目,我们成功地实现了一个基于HTTP/1.1协议的文件管理服务器。我们的服务器能够处理各种文件管理操作,并提供了目录列表、文件下载、文件上传和文件删除的功能。我们的自定义框架和数据结构使我们能够高效地处理和表达HTTP消息的各个部分。
- 验证 Cookie:函数首先检查请求头部中是否包含
-