序列化:结构化数据转换为字节流数据。
反序列化:字节流转换为结构化数据。
作用:
协议定制:
JSON(JavaScript对象表示法)是一种轻量级的数据交换格式,易于人们阅读和编写,也易于机器解析和生成。
它是一种完全与语言无关的文本格式,但使用了C系列语言程序员熟悉的约定,包括C、C++、C#、Java、JavaScript、Perl、Python等等。
JSON通常用于在服务器和Web应用程序之间传输数据,作为XML的替代方案。它也常用于配置文件和数据存储。JSON数据表示为键值对,其中键是字符串,值可以是字符串、数字、布尔值、数组或其他JSON对象。
将客户端发送的结构化数据序列化为字节流式,将字节流式数据从网络传输到服务器,再在服务器端进行反序列化,将字节流式数据反序列化为结构化数据进行计算,再将计算结果序列化为字节流式数据再传输到网络中,由客户端接收。
这种,能够保证一端发送时构造的数据,在另一端能够正确进行解析的约定,就是应用层协议。
平时我们俗称的 “网址” ,其实就是说的 URL。
协议名称://server ip[:80]/a/b/c/d/e.html
->定义互联网中唯一的资源:URL,统一资源定位符
server ip -> 确定唯一的机器
[:80] -> 该服务器提供服务的进程
/a/b/c/d/ -> 客户要访问的资源路径
绝对路径?并非,该资源路径是基于当前web根路径的相对路径
e.html -> 客户要的文件名
全球范围内所有资源,只要找到它的url就能访问该资源。基于这种方式来获取资源称为WWW(World Wide Web),万维网。
像 / ? :
等这样的字符,已经被url当做特殊意义理解了,因此这些字符不能随意出现。
比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义,转义的规则:将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。
urldecode是urlencode的逆过程。
基于请求和响应的这种模式,称之为CS模式。交互的就是双方的报文。
http协议是应用层的协议,底层采用的叫做tcp。http之前已经完成三次握手的动作。
http通过空行的方式区分报头和有效载荷。
#include
#include
#include
#include
#include
#include
#include
#include "Util.hpp"
#include "HttpServer.hpp"
#include "Usage.hpp"
// 一般http都要有自己的web根目录
#define ROOT "./wwwroot"
// 如果客户端只请求了一个/, 返回默认首页
#define HOMEPAGE "index.html"
void HandlerHttpRequest(int sockfd)
{
// 1. 读取请求 for test
char buffer[10240];
ssize_t s = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
if (s > 0)
{
buffer[s] = 0;
}
std::cout << buffer << "\n--------------------\n"
<< std::endl;
std::vector<std::string> vline;
Util::cutString(buffer, "\n", &vline);
std::vector<std::string> vblock;
Util::cutString(vline[0], " ", &vblock);
std::string file = vblock[1];
std::string target = ROOT;
if (file == "/")
file = "/index.html";
target += file;
std::cout << target << std::endl;
std::string content;
std::ifstream in(target);
if (!in.is_open())
{
}
else
{
std::string line;
while (std::getline(in, line))
{
content += line;
}
in.close();
}
std::string HttpResponse;
if (content.empty())
{
HttpResponse = "HTTP/1.1 301 Moved Permanently\r\n";
HttpResponse += "Location: http://8.130.119.166:8081/a/b/404.html\r\n";
}
else
{
HttpResponse = "HTTP/1.1 200 OK\r\n";
HttpResponse += ("Content-Type: text/html\r\n");
HttpResponse += ("Content-Length: " + std::to_string(content.size()) + "\r\n");
HttpResponse += "Set-Cookie: 这是一个cookie\r\n";
}
HttpResponse += "\r\n";
HttpResponse += content;
// std::cout << "########start#################" << std::endl;
// for(auto &iter : vblock){
// std::cout << "---" << iter << "\n" << std::endl;
// }
// std::cout << "##########end###############" << std::endl;
// 2. 试着构建一个http的响应
send(sockfd, HttpResponse.c_str(), HttpResponse.size(), 0);
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
Usage(argv[0]);
exit(0);
}
std::unique_ptr<HttpServer> httpserver(new HttpServer(atoi(argv[1]), HandlerHttpRequest));
httpserver->Start();
return 0;
}
请求:
首行: [方法] + [url] + [版本]
Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束。
Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度。
响应:
首行:[版本号] + [状态码] + [状态码解释]
Header:请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
Body:空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面, 那么html页面内容就是在body中。
常见Header:
Content-Type:数据类型(text/html等)
Content-Length: Body的长度
Host:客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
User-Agent:声明用户的操作系统和浏览器版本信息;
referer:当前页面是从哪个页面跳转过来的;
location:搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;
Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;
表单:收集用户数据,并把用户数据推送给服务器。表单中的数据,会被转成http requst的的一部分。表单一般是需要被提交的,指明提交方法(GRET/POST)。
私密 ≠ 安全,只是明文看不到。
最常见的状态码, 比如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定向), 504(Bad Gateway)。
重定向:当我们进行某些网页请求时,因为功能要求请求登陆其他页面或者网站。
永久重定向(301):影响用户后续的请求策略。
临时重定向(302、307):不影响用户后续的请求策略。
什么可以用来保存记录用户信息?cookie。
- cookie文件:保存用户信息。分为文件级cookie与内存级cookie。
- Set-Cookie:"Set-Cookie"响应头用于服务器向客户端发送cookie。它用于在客户端设备上存储信息,可用于各种目的,如会话管理、用户跟踪和个性化。
- cookie的存在,导致http网络存在安全风险。
- Connection:keep-alive,长链接,可以放多个请求。
- Connection:close,短链接,处理完成一次请求后直接关闭。
HTTP协议内容都是按照文本的方式明文传输的,这就导致在传输过程中,出现一些被篡改的情况。
HTTPS也是一个应用层协议,是HTTP协议的基础上引入了一个加密层。
因为http的内容是明文传输的,明文数据会经过路由器、wifi热点、通信服务运营商、代理服务器等多个物理节点,如果信息在传输过程中被劫持,传输的内容就完全暴露了。劫持者还可以篡改传输的信息且不被双方察觉,这就是中间人攻击
,所以我们才需要对信息进行加密。
加密就是把明文(要传输的信息)进行一系列变换,生成密文。
解密就是把密文再进行一系列变换,还原成明文。
在这个加密和解密的过程中,往往需要一个或者多个中间的数据,辅助进行这个过程,这样的数据称为密钥。
加密与解密到如今已经发展成一个独立的科学:密码学。密码学的奠基人,艾伦·麦席森·图灵。
钥和私钥是配对的,最大的缺点就是运算速度非常慢,比对称加密要慢很多
对原始数据进行哈希散列,生成固定的散列值,这个散列值是唯一存在的,叫做该原始数据的数据摘要。
哈希散列是不可逆的,因此数据摘要不能进行解密,即数据摘要不是加密。
原始数据,通过哈希散列->,固定的散列值(数据摘要),通过签名者(CA机构)的私钥加密->签名。
原始数据+签名->证书
不直接加密形成签名,要先hash形成摘要的原因:
非对称加密+对称加密+证书认证:
证书认证:客户端使对证书内的原始数据使用哈希散列,生成固定散列值,用内置的CA机构公钥进行解密,与证书内的签名进行对比。
中间人篡改替换的方法:ARP欺骗、ICMP攻击、假wifi&&假网站等。
HTTPS工作过程中涉及到的密钥有三组:
第一组(非对称加密):用于校验证书是否被篡改。服务器持有私钥(私钥在形成CSR文件与申请证书时获得),客户端持有公钥(操作系统包含了可信任的CA认证机构有哪些,同时持有对应的公钥)。服务器在客户端请求是,返回携带签名的证书。客户端通过这个公钥进行证书验证,保证证书的合法性,进一步保证证书中携带的服务端公钥权威性。
第二组(非对称加密):用于协商生成对称加密的密钥。客户端用收到的CA证书中的公钥(是可被信任的)给随机生成的对称加密的密钥加密,传输给服务器,服务器通过私钥解密获取到对称加密密钥.
第三组(对称加密):客户端和服务器后续传输的数据都通过这个对称密钥加密解密。
其实一切的关键都是围绕这个对称加密的密钥,其他的机制都是辅助这个密钥工作的。第二组非对称加密的密钥是为了让客户端把这个对称密钥传给服务器, 第一组非对称加密的密钥是为了让客户端拿到第二组非对称加密的公钥。