Http协议

文章目录

      • 1.基础介绍
          • 1.1基本介绍
          • 1.2url
            • 协议方案名
            • 登录信息
            • 服务器地址
            • 服务器端口号
            • 带层次的文件路径
            • 查询字符串
            • 片段标识符
            • urlencode和urldecode
          • 1.3额外知识小补充
      • 2.HTTP协议格式
          • 2.1纵观全局来看待一些问题
          • 2.2请求格式的基本了解
          • 2.3如何将HTTP的报头与有效载荷进行分离?
          • 2.4获取浏览器的HTTP请求
          • 2.5http的响应格式
          • 2.6构建http响应
          • 2.7HTTP的版本交换
          • 2.8HTTP的请求方法
          • 2.9http的响应状态码
          • 2.9+(皮一下) HTTP中常见Header
      • 3.cookie和session
          • 3.1引言
          • 3.2什么是cookie
          • 3.3SessionID
      • 4.Https
          • 4.1引言
          • 4.2加密概念
          • 4.3常见的加密手段
            • 4.31对称加密
            • 4.32⾮对称加密
          • 4.4数据摘要(数据指纹)
          • 4.5不同的加密方法分析
            • 4.51只使用对称加密
            • 4.52一方只使用非对称加密
            • 4.53双方都使用非对称加密
            • 4.54非对称加密加对称加密
          • 4.6中间人攻击(MITM)
          • 4.7证书
          • 4.8终级方案:非对称加密 + 对称加密 + 证书认证

1.基础介绍

1.1基本介绍

HTTP(Hypertext Transfer Protocol)是一种用于传输超文本的应用层协议。它是在Web应用中最为常用的协议之一,用于在客户端和服务器之间传输数据。

其多工作在tcp协议之上,是由大佬在软件层编写的一个协议。

1.2url

URL是用于标识和定位资源的字符串格式,HTTP是一种用于传输超文本的协议,它通过URL来指定要访问的资源。(实际上就是我们所说的网址)

让我们来看看其基础结构:
Http协议_第1张图片

协议方案名

http://表示的是协议名称 ,表示请求时需要使用的协议 ,通常使用的是HTTP协议或安全协议HTTPS。

登录信息

usr:pass表示的是登录认证信息 。(包括登录用户的用户名和密码)

虽然登录认证信息可以在URL中体现出来, 但绝大多数URL的这个字段都是被省略的 因为登录信息可以通过其他方案交付给服务器。

服务器地址

www.example.jp表示的是服务器地址 ,也叫做域名。

而域名实际上就是为了方便我们记忆而设计出来和IP地址一一对应的助记符。

服务器端口号

在进行套接字编程时我们需要给服务器绑定对应的IP和端口, 而这里的应用层协议也同样需要有明确的端口号。

常见协议对应的端口号:

协议名称 对应端口号
HTTP 80
HTTPS 443
SSH 22

实际上0~1023的端口号,早在互联网发展的初期已经被确定好了,就比如说我们上面举例的这些。

带层次的文件路径

/dir/index.htm表示的是要访问的资源所在的路径,就好比在计算机磁盘系统上要确定一个文件的位置就需要用到这一路径信息。

查询字符串

uid=1表示的是发送网络请求时提供的额外的参数 ,这些参数是以键值对的形式 通过&符号分隔开的。

当我们在百度上搜索HTTP的时候可以在最上面的URL发现这样一段文字:

Http协议_第2张图片

这代表着我们的搜索关键字是HTTP协议。

片段标识符

ch1是一个片段标识符。

片段标识符是指URL中的一个特殊字符“#”后面的部分 ,它通常用于指定文档中的某个位置。

例如HTML文档中的锚点 在浏览器中 ,当用户点击一个链接时 ,浏览器会自动滚动到该链接指定的位置。

片段标识符不会被发送到服务器, 因此不会影响服务器的响应。

urlencode和urldecode

urlencodeurldecode是用于处理URL中特殊字符的编码和解码函数。

它将URL中的非字母数字字符替换为百分号(%)后跟两个表示字符ASCII码的十六进制值。这样做是为了确保URL在传输过程中不会出现冲突或错误(比如说用在传网址的时候用了个空格符号)。

1.3额外知识小补充

我们发起网页请求时,我们实际上是向服务器发送了一个HTTP请求。服务器接收到请求后,会根据请求的内容和参数进行处理,并返回一个HTTP响应。

HTTP响应中包含了网页的信息,包括HTML、CSS、JavaScript等资源文件。这些资源文件会被浏览器解析和渲染,最终呈现给用户的是一个完整的网页。因此,我们可以说我们通过发起网页请求得到了一个完整的网页。

2.HTTP协议格式

2.1纵观全局来看待一些问题

Http协议_第3张图片

这张图片想必大家也不陌生,我们接下来的博客顺序也是采用了自顶向下来为大家一一介绍。

实际上在这四层协议当中,下三层主要负责的是建立起通信过程中的细节设计,而应用层则负责的是在建立好了链接有了这一套基础上我们将如何处理这些传递上来的数据来满足我们的具体需求。

比如HTTP这一套基于请求和响应的应用层访问就是典型的应用层协议代表,而想要更好的了解这一协议究竟做了什么我们必须要了解HTTP的请求和响应格式

2.2请求格式的基本了解

Http协议_第4张图片

我们可以看到HTTP请求由四部分组成

  • 请求行:[请求方法]+[url]+[http版本]
  • 请求报头:请求的属性 。这些属性都是以key: value的形式按行陈列的。
  • 空行:遇到空行表示请求报头结束。
  • 请求正文:请求正文允许为空字符串。 如果请求正文存在 ,则在请求报头中会有一个Content-Length属性来标识请求正文的长度。
2.3如何将HTTP的报头与有效载荷进行分离?

如图可以看出这里的报头 = 请求行+请求报头

有效载荷 = 请求正文

从图上可以看出, 报头和有效载荷之间隔着一个空行。

如果我们将整个http协议想象成一个线性的结构, 每一行都是使用\n来进行分隔的 ,那么如果我们连续读取到**两个\n**的话就说明报头读取完毕了。

2.4获取浏览器的HTTP请求

我们的浏览器向服务器发送请求时,起的作用相当于我们之前写的客户端给我们的服务端发送了一段消息,那么我们现在只需要写个服务器,就能查看这段消息的具体格式。

服务器代码如下:

int main()
{
    int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sock < 0)
    {
        cerr << "socket error" << endl;
        exit(1);
    }

    struct sockaddr_in local;
    memset(&local, '\0', sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(8081);
    local.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0)
    {
        cerr << "bind error" << endl;
        exit(2);
    }


    if (listen(listen_sock, 5) < 0)
    {
        cerr << "listen error" << endl;
        exit(3);
    }

    struct sockaddr_in peer;
    memset(&peer, '\0', sizeof(peer));
    socklen_t len;

    for (;;)
    {
        int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
        if (sock < 0)
        {
            cerr << "accept error" << endl;
            continue;
        }

        if (fork() == 0)
        {
            // father     
            close(listen_sock);
            if (fork() > 0)
            {
                // father    
                exit(0);
            }

            // child     
            char buff[1024];
            recv(sock, buff, sizeof(buff), 0);


            cout << "-------- -------- http request begin -------" << endl;
            cout << buff << endl;
            cout << "-------- -------- http request end   -------" << endl;

            close(sock);
            exit(0);
        }


        close(sock);
        waitpid(-1, nullptr, 0);
    }


    return 0;
}

运行服务器之后我们就可以使用浏览器访问了:

Http协议_第5张图片

2.5http的响应格式

Http协议_第6张图片

2.6构建http响应
  string http_response = "http/1.0 200 OK\n";    
  http_response += "Content-type : text/plain\n";    
  http_response += "\n";    
  http_response += "HELLO HTTP";    

  send(sock , http_response.c_str() , http_response.size() , 0);  

响应的代码格式如上 ,如果此时网页端访问我们的服务器 ,我们的服务器就能得到这个http的响应:

Http协议_第7张图片

上面的格式就是我们HTTP响应的格式 ,其中关键字是什么意思,我们将在后文展开。

2.7HTTP的版本交换

HTTP请求是由客户端发的 ,因此HTTP请求当中表明的是客户端的http版本。

而HTTP响应是由服务器发的, 因此HTTP响应当中表明的是服务器的http版本。

客户端和服务器双方在进行通信时会交互双方http版本,主要还是为了兼容性的问题, 因为服务器和客户端使用的可能是不同的http版本。 为了让不同版本的客户端都能享受到对应的服务, 此时就要求通信双方需要进行版本协商。

2.8HTTP的请求方法
方法 说明 支持的HTTP协议版本
GET 获取资源 1.0、1.1
POST 传输实体主体 1.0、1.1
PUT 传输文件 1.0、1.1
HEAD 获得报文首部 1.0、1.1
DELETE 删除文件 1.0、1.1
OPTIONS 询问支持的方法 1.1
TRACE 追踪路径 1.1
CONNECT 要求用隧道协议连接代理 1.1
LINK 建立和资源之间的联系 1.0
UNLINK 断开连接关系 1.0

其中我们最常用的就是get和post这两种方法。

一般来说GET方法用于获取资源 而POST方法用于上传资源 ,但是事实上GET方法也可以用来上传数据 ,POST方法也可以用来请求数据 ,比如说我们使用百度提交数据的时候我们使用的就是GET方法。

get与post的区别

GET方法和POST方法都可以带参 但是它们的传参方式有所不同

  • GET方法是通过url传参的
  • POST方法是通过正文传参的

从它们的传参方式我们就可以看出 GET方法传递的参数是有限的 ,因为url的长度是有限的。

而POST方法能够传递更多的参数 ,因为正文的限制长度比url的限制长度多得多。

此外我们使用POST传参更加私密一点。

因为当我们使用GET方法传参的时候参数会暴露在url中, 而POST方法则不会。

所以我们可以说POST方法比GET方法安全一点。

但是实际上这两种方法都是不安全的 ,它们都能够被抓包工具抓包从而导致信息泄漏, 想要数据安全我们只能对于这些信息进行加密,后面我们讲的https就是来专门处理这种情况的。

2.9http的响应状态码
编号 类别 意义
1XX Informational(信息性状态码) 接收的请求正在处理
2XX Success(成功状态码) 请求正常处理完毕
3XX Redirection(重定向状态码) 需要进行附加操作以完成请求
4XX Client Error(客户端错误状态码) 服务器无法处理请求
5XX Server Error(服务器错误状态码) 服务器处理请求出错

下面会介绍一些常用的:

101: 信息请求中

200: OK(访问网页成功的时候网页返回的响应行)

301: 永久重定向(比如果一个老的网站废弃不用了使用一个新的网站 ,那么此时这个网站就可以使用永久重定向 ,如果有人还在访问这个网站就会跳转到新网站)

302 307:临时重定向( 和301永久重定向相比一个是永久的一个是临时的 ,它并不会覆盖掉收藏夹中的老网站)

403 :权限不足(这个常见于我们去实习的时候 ,自己的权限特别低 如果leader丢给你一个文档而你没有观看的权限就会出现这个状态码)

404 :NOT FOUND(常见于资源消失不见(被删除或过期) 又或者说资源根本不存在)

504 :Bad Gateway(常见于服务器出现问题 和客户端无关)

2.9+(皮一下) HTTP中常见Header

HTTP常见的Header如下:

  • Content-Type:数据类型(text/html等)
  • Content-Length:正文的长度
  • Host:客户端告知服务器 所请求的资源是在哪个主机的哪个端口上
  • User-Agent:声明用户的操作系统和浏览器的版本信息
  • Referer:当前页面是哪个页面跳转过来的
  • Location:搭配3XX状态码使用 告诉客户端接下来要去哪里访问
  • Cookie:用于在客户端存储少量信息 通常用于实现会话(session)的功能

3.cookie和session

3.1引言

HTTP实际上是一种无状态协议 ,HTTP的每次请求/响应之间是没有任何关系的

但是日常生活中往往有这样的现象,比如你用账号密码登录b站后,下一次在打开b站,你会发现账号是自动登录状态。这是为什么呢?
原来在我们的cookie中保存了这些信息,使得我们自动完成了登录。

Http协议_第8张图片

3.2什么是cookie

Cookie是一种用于在客户端和服务器之间存储小段数据的技术。Cookie通常由服务器发送到客户端,然后客户端将其存储并在后续HTTP请求中将其发送回服务器。这些小段数据可以包含用户的会话信息、首选项、状态信息等,以便在不同HTTP请求之间保持持久性。

Http协议_第9张图片

内存级别&文件级别

cookie就是在浏览器当中的一个小文件, 文件里记录的就是用户的私有信息。

cookie文件可以分为两种: 一种是内存级别的cookie文件, 另一种是文件级别的cookie文件。

  • 将浏览器关掉后再打开, 访问之前登录过的网站 。如果需要你重新输入账号和密码, 说明你之前登录时浏览器当中保存的cookie信息是内存级别的。
  • 将浏览器关掉甚至将电脑重启再打开 ,访问之前登录过的网站 。如果不需要你重新输入账户和密码 ,说明你之前登录时浏览器当中保存的cookie信息是文件级别的。
3.3SessionID

如果单纯的使用cookie技术的化那么cookie里面直接存放着的是你的私人信息,如果被人偷取了显然会造成很糟糕的结果。

那么为了避免这样的情况产生,我们可以给你的私人信息套上一层转换机制,这就是我们的SessionID的由来。

当我们首次登录某个网站的时候 ,该网站对应的服务器会生成一个SessionID 。该ID是和用户的信息是一一对应的 ,生成该ID之后网站会将用户的信息保存到服务器的某个特定目录当中。

这样子就算用户的SessionID被盗取了也不会影响用户隐私安全。

Http协议_第10张图片

其实这样做也不是绝对安全的,黑客也可以直接截取你sessionid的值来以用户的方式访问网站。(说白了就是往一个人身上套了一层皮套,你看不到他的真实长相,但是皮套人和那个真人还是呈现一一对应关系)

具体如何更进一步的使我们的消息更加安全便不是我们主要讨论的能容,在这里也就不深入探讨了。

4.Https

4.1引言

好终于到了这一部分,前面的文章基本是介绍了一些概念相关的东西,仔细看都能看懂,而这一部分我们将涉及到一定的推理,有点小难度,当然也不必害怕,我会尽可能的将这些繁杂的内容一一道来,好废话不多说,直接进入正文。

Https实质也是一个应用层协议,上面我们说的http协议内容都是按照明文的方式传输的,非常不安全,因此在http的基础下我们的https引入了一层加密层。

4.2加密概念

什么是加密?

加密就是把 明⽂ (要传输的信息)进⾏⼀系列变换, ⽣成 密⽂ 。

解密就是把 密⽂ 再进⾏⼀系列变换, 还原成 明⽂ 。

在这个加密和解密的过程中, 往往需要⼀个或者多个中间的数据, 辅助进⾏这个过程, 这样的数据称为

。 (正确发⾳ yue 四声, 不过⼤家平时都读作 yao 四声)

4.3常见的加密手段
4.31对称加密

采⽤单钥密码系统的加密⽅法,同⼀个密钥可以同时⽤作信息的加密和解密,这种加密⽅法称为对

称加密,也称为单密钥加密。特征:加密和解密所⽤的密钥是相同的

特点:算法公开、计算量⼩、加密速度快、加密效率⾼

当然密钥这玩意到底是如何加密解密的下面举个简单的例子:

⼀个简单的对称加密, 按位异或

比特就业课假设 明⽂ a = 1234, 密钥 key = 8888

则加密 a ^ key 得到的密⽂ b 为 9834.

然后针对密⽂ 9834 再次进⾏运算 b ^ key, 得到的就是原来的明⽂ 1234.

(对于字符串的对称加密也是同理, 每⼀个字符都可以表⽰成⼀个数字)

当然, 按位异或只是最简单的对称加密. HTTPS 中并不是使⽤按位异或.

4.32⾮对称加密

需要两个密钥来对明文进⾏加密和解密,这两个密钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。

可以用公钥来加密,私钥来解密,当然也可以用私钥来加密,公钥来解密。

公钥和私钥是配对的,最⼤的缺点就是运算速度⾮常慢,⽐对称加密要慢很多

4.4数据摘要(数据指纹)

• 数字指纹(数据摘要),其基本原理是利⽤单向散列函数(Hash函数)对信息进⾏运算,⽣成⼀串固定⻓度

的数字摘要。数字指纹并不是⼀种加密机制,但可以⽤来判断数据有没有被窜改。

• 摘要常见算法:有MD5、SHA1、SHA256、SHA512等,算法把⽆限的映射成有限,因此可能会有

碰撞(两个不同的信息,算出的摘要相同,但是概率非常低)

• 摘要特征:和加密算法的区别是,摘要严格意义不是加密,因为没有解密,只不过从摘要很难反推

原信息,通常⽤来进⾏数据对⽐

简单例子:

首先,选择一个哈希函数。常见的哈希函数包括MD5、SHA-1、SHA-256等。这里我们使用一个简单的示例,假设我们有一个自定义的哈希函数,它将字符串中的每个字符转换为ASCII码,然后将这些ASCII码值相加,最后取余数,以得到一个固定长度的数字摘要。

4.5不同的加密方法分析
4.51只使用对称加密

通信双⽅都各⾃持有同⼀个密钥X

Http协议_第11张图片

引⼊对称加密之后, 即使数据被截获, 由于⿊客不知道密钥是啥, 因此就⽆法进⾏解密, 也就不知道请求

的真实内容是啥了。

但事情没这么简单. 服务器同⼀时刻其实是给很多客⼾端提供服务的. 这么多客⼾端, 每个⼈⽤的秘钥都

必须是不同的。

Http协议_第12张图片

当然比较理想的做法是下面这幅图:

Http协议_第13张图片

​ 但是如果直接把密钥明⽂传输, 那么⿊客也就能获得密钥了~~ 此时后续的加密操作就形同虚设了

4.52一方只使用非对称加密

Http协议_第14张图片

4.53双方都使用非对称加密

Http协议_第15张图片

​ 这种情况看似很安全,其实也不安全(后面会一一道来),而且效率太低。

4.54非对称加密加对称加密

Http协议_第16张图片

4.6中间人攻击(MITM)

当然针对上面的情况来说已经很接近正确答案了,但是仍然会存在安全问题。

在方案2/3/4中,第一步都是将公钥发送给对方,但如果此时黑客就进行拦截呢?

比如:中间人劫持数据报文,提取公钥S并保存好,然后将被劫持报⽂中的公钥S替换成为自己的公钥M,

并将伪造报文发给客户端

如果这样会发生什么,我们以方案4为例子为大家画一幅图进行讲解。

Http协议_第17张图片

4.7证书

为了解决上述问题我们引进了证书这一概念。

CA认证

服务端在使⽤HTTPS前,需要向CA机构申领⼀份数字证书,数字证书⾥含有证书申请者信息、公钥信

息等。服务器把证书传输给浏览器,浏览器从证书⾥获取公钥就⾏了,证书就如⾝份证,证明服务端

公钥的权威性

当服务端申请CA证书时候,CA机构会对该服务端进行审核,并专门为该网站形成数字签名,过程如下:

1.CA机构拥有非对称加密的私钥A和公钥A’

2.CA机构对服务端申请的证书明文数据进行hash

3.然后对数据摘要用CA的密钥A’加密,形成签名

图示:

Http协议_第18张图片

为什么签名不直接加密,⽽是要先hash形成摘要?

• 缩⼩签名密⽂的⻓度,加快数字签名的验证签名的运算速度

4.8终级方案:非对称加密 + 对称加密 + 证书认证

Http协议_第19张图片

你可能感兴趣的:(linux,http,网络协议,网络)