网络云盘项目——HTTP接口介绍功能介绍服务端/客户端代码解析
Posted 董哥的黑板报
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络云盘项目——HTTP接口介绍功能介绍服务端/客户端代码解析相关的知识,希望对你有一定的参考价值。
一、本文目的
- 本项目分为6篇博客文章完成:
- 1.项目总体介绍:https://blog.csdn.net/qq_41453285/article/details/107871393。
- 2.Redis部署、MySQL部署、MySQL表设计:https://blog.csdn.net/qq_41453285/article/details/107871620。
- 3.FastDFS部署:https://blog.csdn.net/qq_41453285/article/details/107874068。
- 4.Nginx配置:https://blog.csdn.net/qq_41453285/article/details/107889933。
- 5.服务端/客户端部署、演示运行效果:https://blog.csdn.net/qq_41453285/article/details/107891262。
- 6.HTTP接口介绍、功能介绍、服务端/客户端代码解析:本文介绍的。
源码下载方式
- 方式1:公众号《董哥的黑板报》回复【3578】获取百度云盘链接。
- 方式2:Github开源链接GitHub - dongyusheng/cloud-disk: 网络云盘。
- 本文的东西有点多,主要是对服务端与客户端的代码进行解析。
备注
- 在使用百度网盘的时候需要先指定服务端的IP和端口。
- 点击主页的右上角。
- 来到下面这个画面,设置服务端的IP和端口(服务端程序的地址和nginx的运行端口)。
二、注册功能
HTTP接口介绍
- HTTP请求相关字段:
URL http://111.229.177.161/reg 请求方式 POST HTTP版本 1.1 Content-Type application/json
- HTTP请求主体如下:
参数名 含义 规则说明 是否必须 缺省值 邮箱 必须符合 email 规范 可选 无 firstPwd 密码 md5 加密后的值 必填 无 nickName 用户昵称 不能超过 32 个字符 必填 无 phone 手机号码 不能超过 16 个字符 可选 无 userName 用户名称 不能超过 32 个字符 必填 无
- HTTP响应报文的主体为:
参数名 含义 规则说明 code 结果值 002:成功
003:该用户已存在
004:失败
业务流程如下
- Qt客户端通过发送一个HTTP请求给Nginx(URL以reg结尾),Nginx接收到这个请求将请求传递给FastCGI,FastCGI通过自己一些内置的环境变量获取到URL和报文主体进行解析。
运行与抓包演示
- 打开Fiddler抓包工具:随便你们用什么工具,只要能抓包就行。
- 开启服务端:在前面一篇文章已经介绍了。
- 运行Qt客户端:点击注册,然后来到下面输入如下的内容。
- 点击注册之后,可以看到Fiddler抓到了一个包。
- 查看这个HTTP请求报文的请求行和首部行:
- 使用POST方式请求。
- 访问的url为/reg。
- 并且Content-Type是application/json格式的,说明报文主体是JSON格式的(见下)。
- 查看报文主体:可以看到自己注册输入的信息(与上面的HTTP接口介绍是一样的)。
- HTTP响应报文如下:可以看到服务端的响应报文的主体是002。
- 然后查看MySQL数据库,可以看到user_info表中插入了我们新注册的一个用户。
Qt客户端代码解析
- 点击了注册按钮之后,会在login.cpp文件中响应on_register_btn_clicked()函数。
- 然后首先判断你这些输入的内容格式是否正确,使用到了QRegExp类。
- 然后调用setRegisterJson()函数将你所输入的内容转换为JSON格式(作为HTTP请求报文的主体发送出去)。
- setRegisterJson()函数比较简单,就是将所有的内容设置为JSON格式保存。
- setRegisterJson()函数调用完之后,下面开始构造URL和请求报文,并且将请求报文的头部和主体部分发送出去。
- 然后等待服务端给自己的回送消息并解析,因为服务端给自己返回的内容也是JSON格式的,因此我们解析JSON中“code”字符串的值,然后再做相关的判断。
服务端代码解析
- 我们的服务端是Nginx服务器+FastCGI。
- 可以通过查看Nginx的配置文件,当Nginx接收到的URL中含有/reg时(注册),就会将请求转发给127.0.0.1:10001这个FastCGI程序进行处理。
- 通过服务端的脚本(fcgi.sh)可以看到,127.0.0.1:10001这个FastCGI名为register。
- 也就是我们服务端编译好的bin_cgi/register程序。
- register程序的源码为src_cgi/reg_cgi.c。
- 查看reg_cgi.c的main函数,FastCGI程序通过内置的“CONTENT_LENGTH”环境变量,获得HTTP请求报文的主题部分是有内容(长度是否大于0),如果没有内容就报错,如果有内容就获取用户的的注册信息。
- 如果HTTP请求报文有内容,那么就调用fread()从Nginx中读取HTTP请求报文的所有内容,然后调用user_register()函数在服务端注册该用户。
- 查看user_register()函数可以看到:
- 调用get_mysql_info():获取MySQL数据库的相关信息(IP、端口等),然后保存到字符串中,因为我们后面要连接数据库。
- 调用get_reg_info():因为HTTP请求报文中的主题部分是JSON格式的,因此我们在get_reg_info()调用JSON的C API,将JSON信息出来,获得里面的用户名、密码等。
- 调用mysql_conn():连接MySQL。
- 调用process_result_one():查看这个用户是否在MySQL中已经存在了,存在的话就不注册了。
- 调用mysql_query():构造一条SQL语句,然后这条用户数据插入到user_info表中。
- 之后返回结果。
- 最后退出user_register()函数,再次来到main()函数:
- 根据user_register()函数的返回结果判断用户是否注册功能,如果注册成功的话调用return_status()构造一个字符串out。
- 然后调用printf()将out返回给Nginx。
- return_status()函数:就是将相应内容构造为JSON格式,然后返回给Nginx,Nginx又会返回给Qt客户端。
备注(MD5)
- 客户端登录的时候会把用户的密码经过md5加密,然后再传递给服务端。
- MD5 即 Message-Digest Algorithm 5(信息-摘要算法 5),用于确保信息传输完整一致。是计 算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有 MD5 实现。
- 理论上 MD5 是不可逆的,而且 MD5 本来也不是作加密使用,而是用来校验数据的完整性, 只是因为其不可逆且稳定、快速的特点,被广泛用于对明文密码的加密。
- 但是简单密码来说,破解者完全可以将一定范围内的密码字典全部计算出来之后存为数据 库,之后直接查询进行破解。
三、登录
- 登录的时候会发送两个URL请求报文给服务端:
- /login URL:用来判断这个用户的账号和密码是否正确(服务端从MySQL中判断)。
- /myfiles?cmd=count URL:登录成功之后,Qt客户端再发送一个请求获得自己的文件数量。
- /myfiles?cmd=normal:上面知道了自己有多少个文件之后,发送这个URL来获取自己的文件。
登录HTTP接口介绍
- HTTP请求相关字段:
URL http://111.229.177.161/login 请求方式 POST HTTP版本 1.1 Content-Type application/json
- HTTP请求主体如下:
参数名 含义 规则说明 是否必须 缺省值 pwd 密码 md5加密后的值 必填 无 user 用户名称 不能超过32个字符 必填 无
- HTTP响应报文的主体为:
参数名 含义 规则说明 code 结果值 000:成功
001:失败
token 令牌 每次登录后,生成的token都不一样
获取文件数量HTTP接口介绍
- HTTP请求相关字段:
URL http://111.229.177.161/myfiles?cmd=count 请求方式 POST HTTP版本 1.1 Content-Type application/json
- HTTP请求主体如下:
参数名 含义 规则说明 是否必须 缺省值 token token 同上 必填 无 user 用户名称 不能超过32个字符 必填 无
- HTTP响应报文的主体为:
参数名 含义 规则说明 code 结果值 110:验证成功
111:验证失败
num 文件数量
获取文件信息HTTP接口介绍
- HTTP请求相关字段:
URL http://111.229.177.161/myfiles?cmd=normal 请求方式 POST HTTP版本 1.1 Content-Type application/json
- HTTP请求主体如下:
参数名 含义 规则说明 是否必须 缺省值 token token 同上 必填 无 user 用户名称 不能超过32个字符 必填 无 count 文件个数 文件个数需要大于0 必填 无 start 开始位置 必填 无
- HTTP响应报文的主体为:
参数名 含义 规则说明 files 文件结果集 "user":用户名称
"md5":md5值
"create_time":创建时间
"file_name":文件名
"share_status":共享状态,0为没有贡献
"pv":文件下载量,下载1次就加1
"url":URL
"size":文件大小
"type":文件类型
登录业务流程如下
- Qt客户端通过发送一个HTTP请求给Nginx(URL以login结尾),Nginx接收到这个请求将请求传递给FastCGI,FastCGI通过自己一些内置的环境变量获取到URL和报文主体进行解析。
获取文件数量和获取文件业务流程如下
- 登录之后先调用/myfiles?cmd=count来获取自己在服务端拥有文件的数量,如果没有文件就结束,如果有文件再调用myfiles?cmd=normal来获取自己在服务端的文件的数量。
运行与抓包演示
- 开启服务端:在前面一篇文章已经介绍了
- 运行Qt客户端:登录的时候,我们输入一个错误的吗
- 可以看到Fiddler抓到一个包
- 查看包:
- 上面的为请求报文的主体部分:密码是错误的
- 下面为响应报文的主体部分:可以看到服务端给我们回送的code为001表示失败
- 重新登录,这次输入正确的账号和密码,然后登录成功进入下面的页面,并且我们有一个文件
- 登录的时候Qt客户端会发送3个HTTP请求:
- /login:用来验证登录的
- /myfiles?cmd=count:登录成功之后才会接着发送这个HTTP请求(否则不发送这个请求),来获取自己有多少个文件
- /myfiles?cmd=normal:上面知道了自己有多少个文件之后,发送这个URL来获取自己的文件
- login请求如下:可以看到服务端给我们回送的code为000,并且给我们返回了一个token
- /myfiles?cmd=count请求如下:
- 上面为请求报文的主体部分:Qt客户端给服务端发送自己的用户名和token,要求获得自己的文件数量
- 下面为响应报文的主体部分:因为我们有一个文件,所以其返回的num字段为1
- 进入MySQL查看,dongshao拥有的文件确实是一个
- /myfiles?cmd=normal请求如下:
- 上面为请求报文的主体部分:客户端发送设置count为1(通过上面的请求知道自己有1个文件)
- 下面为响应报文的主体部分:返回这个文件的信息
- 因为我们的服务端会把客户端的token保存到Redis中,因此登录Redis查看,可以看到这次登录用户的token为
Qt客户端代码解析
- 点击了注册按钮之后,会在login.cpp文件中响应on_login_btn_clicked()函数
- 首先获取你输入的用户名和密码,还有服务端的地址,然后判断用户名和密码格式
- 然后发送/login URL,并且将相关数据也发送给服务端
- 之后等待服务端的响应,如果服务端返回的code为000,则显式出窗口
- 转到上面的主界面显示窗口showMainWindow()函数,其会调用refreshFiles()函数获取用户文件列表
- refreshFiles()函数构造一个/myfiles?cmd=count URL给服务端,来获得自己在服务端拥有的文件数量
- 获得自己的文件数量之后,调用getUserFilesList()函数获得文件的所有内容
- getUserFilesList()函数有很多作用,其中包括发送一个/myfiles?cmd=normal URL给服务端获得所有的文件
- 之后获得文件并显示
服务端代码解析
- 服务端在接收到/login和/myfiles的URL之后,会调用127.0.0.1:10000和127.0.0.1:10004这两个FastCGI,其中127.0.0.1:10000用于处理登录,127.0.0.1:10004用于处理文件
- 通过服务端的脚本(fcgi.sh)可以看到,127.0.0.1:10000这个FastCGI名为login,127.0.0.1:10004这个FastCGI名为myfiles
- 也就是我们服务端编译好的bin_cgi/login程序和bin_cgi/myfiles
- register程序的源码为src_cgi/reg_cgi.c
- login程序是用login_cig.c实现的,先来看看登录功能
- 与之前一样,先通过CONTENT_LENGTH环境变量来获取HTTP请求报文主体是否有内容,有内容才进一步分析
- 然后:
- 调用fread从Nginx读取数据
- 调用调用get_login_info()函数获取登录的用户名和密码
- 之后再调用check_user_pwd()从MySQL判断这个用户的相关信息是否正确
- 如果登录信息正确,那么就调用set_token()给这个客户端随机生成一个token保存在redis中,然后调用return_login_status()给前端返回数据
- 当URL以myfiles结尾时就会调用myfiles_cgi.c程序,来是处理文件的操作
- 先通过QUERY_STRING解析URL格式,判断URL的?后面是什么内容(例如可以是myfiles?cmd=count或者myfiles?cmd=normal等);然后再通过CONTENT_LENGTH判断请求报文主题是否有内容
- 然后判断?后面是什么内容,如果是count,说明是获取文件数量,否则可能是获取文件信息/按下载量升序/按下载量降序
- 后面的代码就不解析了,可以自己看看
备注(token验证)
- 可以看到客户端在登录了服务端之后,服务端会为其生成一个token,并保存到redis中
- Token 的中文有人翻译成 “令牌”,意思就是,你拿着这个令牌,才能过一些关卡
- Token 是一个用户自定义的任意字符串。在成功提交了开发者自定义的这个字符串之后, Token 的值会保存到服务器后台。只有服务器和客户端前端知道这个字符串,于是 Token 就 成了这两者之间的密钥,它可以让服务器确认请求是来自客户端还是恶意的第三方
- 这里所说的 Token,本质上就是 http session
- 使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这 样的:
- 1) 客户端使用用户名跟密码请求登录
- 2) 服务端收到请求,去验证用户名与密码
- 3) 验证成功后,服务端生成一个 Token,这个 Token 可以存储在内存、磁盘、或者数据库 里,再把这个 Token 发送给客户端
- 4) 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage
- 5) 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
- 6) 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户 端返回请求的数据
备注(Base64)
- 用记事本打开 exe、jpg、pdf 这些文件时,我们都会看到一大堆乱码,因为二进制文件包含很多无法显示和打印的字符
- 所以,如果要让记事本这样的文本处理软件能处理二进制数据,如使用 json 保存二进制信 息,需要先把数据先做一个 Base64 编码,统统变成可见字符,再保存
- 在 Base64 中的可打印字符包括大写英文字母 A-Z、小写英文字母 a-z、阿拉伯数字 0-9,这 样共有 62 个字符,此外两个可打印符号在不同的系统中而不同,通常用加号(+)和正斜 杠(/)。外加“补全符号”,通常用等号(=)
- Base64 是一种用 64 个字符来表示任意二进制数据的方法,常用于在 URL、Cookie、网页中 传输少量二进制数据
- Base64 要求把每三个 8Bit 的字节转换为四个 6Bit 的字节(3*8 = 4*6 = 24),然后把 6Bit 再添两位高位 0,组成四个 8Bit 的字节,也就是说,转换后的字符串理论上将要比原来的长 1/3。
四、按下载量升序
HTTP接口介绍
- HTTP请求相关字段:
URL http://111.229.177.161/myfiles?cmd=pvasc 请求方式 POST HTTP版本 1.1 Content-Type application/json
- HTTP请求主体如下:
参数名 含义 规则说明 是否必须 缺省值 token 令牌 同上 必填 无 user 用户名称 不能超过32个字符 必填 无 count 数量 必填 无 start 开始位置 可选 无
- HTTP响应报文的主体为:
参数名 含义 规则说明 files 文件结果集 "user":用户名称
"md5":md5值
"create_time":创建时间
"file_name":文件名
"share_status":共享状态,0为没有贡献
"pv":文件下载量,下载1次就加1
"url":URL
"size":文件大小
"type":文件类型
业务流程如下
- Qt客户端通过发送一个HTTP请求给Nginx(URL以reg结尾),Nginx接收到这个请求将请求传递给FastCGI,FastCGI通过自己一些内置的环境变量获取到URL和报文主体进行解析
五、按下载量降序
HTTP接口介绍
- HTTP请求相关字段:
URL http://111.229.177.161/myfiles?cmd=pvdesc 请求方式 POST HTTP版本 1.1 Content-Type application/json
- HTTP请求主体如下:
参数名 含义 规则说明 是否必须 缺省值 token 令牌 同上 必填 无 user 用户名称 不能超过32个字符 必填 无 count 数量 必填 无 start 开始位置 可选 无
- HTTP响应报文的主体为:
参数名 含义 规则说明 files 文件结果集 "user":用户名称
"md5":md5值
"create_time":创建时间
"file_name":文件名
"share_status":共享状态,0为没有贡献
"pv":文件下载量,下载1次就加1
"url":URL
"size":文件大小
"type":文件类型
业务流程如下
- Qt客户端通过发送一个HTTP请求给Nginx(URL以reg结尾),Nginx接收到这个请求将请求传递给FastCGI,FastCGI通过自己一些内置的环境变量获取到URL和报文主体进行解析
六、查看共享文件
- 当点击了共享列表之后,就可以查看共享文件了,共享文件的查看需要发送两个HTTP请求:
- sharefiles?cmd=count:先获取共享文件的数量
- sharefiles?cmd=normal:再获取共享文件的列表
获取共享文件数量HTTP接口
- HTTP请求相关字段:
URL http://111.229.177.161/sharefiles?cmd=count 请求方式 POST HTTP版本 1.1 Content-Type application/json
- 没有HTTP请求报文主题,因为不需要任何验证,共享文件大家都可以看到
- HTTP响应报文的主体为:
参数名 含义 规则说明 count 数量
获取共享文件列表HTTP接口
- HTTP请求相关字段:
URL http://111.229.177.161/sharefiles?cmd=normal 请求方式 POST HTTP版本 1.1 Content-Type application/json
- HTTP请求主体如下:
参数名 含义 规则说明 是否必须 缺省值 count 数量 必填 无 start 开始位置 必填 无
- HTTP响应报文的主体为:
参数名 含义 规则说明 files 文件结果集 "user":用户名称
"md5":md5值
"create_time":创建时间
"file_name":文件名
"share_status":共享状态,0为没有贡献
"pv":文件下载量,下载1次就加1
"url":URL
"size":文件大小
"type":文件类型
七、共享文件
获取共享文件数量HTTP接口
- HTTP请求相关字段:
URL http://111.229.177.161/sharefiles?cmd=pv 请求方式 POST HTTP版本 1.1 Content-Type application/json
- HTTP请求主体如下:
参数名 含义 规则说明 是否必须 缺省值 token 令牌 同上 必填 无 user 用户名称 不能超过32个字符 必填 无 md5 md5值 md5加密后的值 必填 无 filename 文件名称 不能超过128个字符 必填 无
- HTTP响应报文的主体为:
参数名 含义 规则说明 code 结果值 010:成功
011:失败
012:别人已经分享此文件
023:token验证失败
业务流程如下
- Qt客户端通过发送一个HTTP请求给Nginx(URL以pv结尾),Nginx接收到这个请求将请求传递给FastCGI,FastCGI通过自己一些内置的环境变量获取到URL和报文主体进行解析
八、删除文件
删除文件数量HTTP接口
- HTTP请求相关字段:
URL http://111.229.177.161/dealfile?cmd=del 请求方式 POST HTTP版本 1.1 Content-Type application/json
- HTTP请求主体如下:
参数名 含义 规则说明 是否必须 缺省值 token 令牌 同上 必填 无 user 用户名称 不能超过32个字符 必填 无 md5 md5值 md5加密后的值 必填 无 filename 文件名称 不能超过128个字符 必填 无
- HTTP响应报文的主体为:
参数名 含义 规则说明 code 结果值 013:成功
004:失败
业务流程如下
- Qt客户端通过发送一个HTTP请求给Nginx(URL以pv结尾),Nginx接收到这个请求将请求传递给FastCGI,FastCGI通过自己一些内置的环境变量获取到URL和报文主体进行解析
九、我的文件下载标志处理
- 自己的文件可以自己下载,下载之后需要调用这个URL
我的文件下载标志处理HTTP接口
- HTTP请求相关字段:
URL http://111.229.177.161/dealfile?cmd=pv 请求方式 POST HTTP版本 1.1 Content-Type application/json
- HTTP请求主体如下:
参数名 含义 规则说明 是否必须 缺省值 token 令牌 同上 必填 无 user 用户名称 不能超过32个字符 必填 无 md5 md5值 md5加密后的值 必填 无 filename 文件名称 不能超过128个字符 必填 无
- HTTP响应报文的主体为:
参数名 含义 规则说明 code 结果值 016:成功
十、取消分享文件
取消分享文件HTTP接口
- HTTP请求相关字段:
URL http://111.229.177.161/dealsharefile?cmd=cancel 请求方式 POST HTTP版本 1.1 Content-Type application/json
- HTTP请求主体如下:
参数名 含义 规则说明 是否必须 缺省值 user 用户名称 不能超过32个字符 必填 无 md5 md5值 md5加密后的值 必填 无 filename 文件名称 不能超过128个字符 必填 无
- HTTP响应报文的主体为:
以上是关于网络云盘项目——HTTP接口介绍功能介绍服务端/客户端代码解析的主要内容,如果未能解决你的问题,请参考以下文章