网络原理---HTTP/HTTPS

发布于:2025-02-26 ⋅ 阅读:(15) ⋅ 点赞:(0)

通过之前的网络编程,我们已经初步了解UDP和TCP的基本实现方法,接下来我们对其进一步的学习。

在网络编程中:

  • 1.读和写数据通过Socket,通过Socket内置的InputStream和OutputStream(读写的基本单位都是字节)。
  • 2.当在编写客户端服务器时,是需要约定响应/请求之间的分隔符的。(\n)
  • 3.服务器这边accept得到的socket对象,记得要及时关闭。
  • 4.要处理多个客户端,需要搭配多线程/线程池。

此时如果客户端进一步增加,此时多线程/线程池就会产生大量线程。在操作系统中内置了IO多路复用,本质上是一个线程同时处理多个客户端的请求。

举个例子,比如此时我需要买三样东西,蛋炒饭,面条,包子,我先来蛋炒饭这里,给老板说来一份蛋炒饭,我一会来拿;我再去面条这里同样来一碗面,等会来拿;包子也是如此,等的过程中,三个老板同时开始工作,过了一会,蛋炒饭老板好了就好喊我....我只用了一份等待的时间,同时等待三个任务的完成,这个过程就类似IO多路复用。

        多个客户端类比多个小摊的老板,每个客户端绝大部分是沉默的;工作线程只需要等待就可以,等到客户端发来数据的时候,线程再来处理就可以了。这个例子把我当成服务器,把几个小摊老板当做客户端,请求就是小贩老板把做好的返给我。

IO多路复用是当前开发服务器的主流核心技术,操作系统内置的,只需要调用api即可。

一、网络初识,认识网络的协议栈

1.应用层

应用程序和应用层直接相关,应用层中的涉及到的网络通信协议,很多都是程序员自己定制的。

1.1如何自定义协议呢?

1.根据需求,明确传输哪些信息。

  • 客户端--服务器 根据需求传递的信息
  • 请求:比如用户的位置信息,用户的ID
  • 响应:比如商家的ID,商家的名字,商家的图片,配送费等

2.约定好信息组织的格式。

比如1).行文本的方式(最原始),比如下面这个例子

2).通过xml格式来约定请求和响应的数据(比较原始,可读性好,冗余较多)。

  • xml是成对的标签构成的键值对结构,标签内容可以自定义;用来网络传输和浏览器怎么显示无关;xml可以用于很多场景,组织一段格式化数据,数据用来网络传输,作为配置文件....

3).json当下最流行的网络数据格式组织的方案(主流的方式,可读性好,冗余一般)

4).protobuf(高性能场景下使用的方式,可读性差,冗余最小)

基于二进制的格式,对数据进行压缩,不涉及到json/xml的冗余信息了,宽带消耗少,可读性变差了。

应用层这里除了自定义协议之外,还有已经写好的协议:FTP 文件传输,SSH 远程操作主机;telnet 网络调试工具,HTTP 协议,HTTPS(是在http基础上+安全层(S表示安全层SSL))。

二、HTTP协议

HTTP(全称为"超⽂本传输协议")是⼀种应⽤⾮常⼴泛的应⽤层协议.

HTTP往往是基于传输层的TCP协议实现的.(HTTP1.0,HTTP1.1,HTTP2.0均为TCP,HTTP3基于 UDP实现)⽬前我们主要使⽤的还是HTTP1.1和HTTP2.0.这里的HTTP以1.1版本为主.我们平时打开⼀个⽹站,就是通过HTTP协议来传输数据的.

1.理解HTTP协议的工作过程

当我们在浏览器中输⼊⼀个"⽹址",此时浏览器就会给对应的服务器发送⼀个HTTP请求.对⽅服务器 收到这个请求之后,经过计算处理,就会返回⼀个HTTP响应.

事实上,当我们访问⼀个⽹站的时候,可能涉及不⽌⼀次的HTTP请求/响应的交互过程.

2. HTTP的协议格式

HTTP是⼀个⽂本格式的协议.可以通过Chrome开发者⼯具或者Fiddler抓包,分析HTTP请求/响应 的细节.

  • 1.HTTP一问一答模式的协议:客户端发一个请求,服务器就返回一个响应,请求与响应一一对应。
  • 2.HTTP报文格式:需要搭配一个重要的工具,抓包工具进行学习。

3.抓包工具的使用

以Fiddler为例.(下载地址:https://www.telerik.com/fiddler/)

  • 左侧窗⼝显⽰了所有的HTTP请求/响应,可以选中某个请求查看详情.
  • 右侧上⽅显⽰了HTTP请求的报⽂内容.(切换到Raw标签⻚可以看到详细的数据格式)
  •  右侧下⽅显⽰了HTTP响应的报⽂内容.(切换到Raw标签⻚可以看到详细的数据格式)
  •  请求和响应的详细数据,可以通过右下⻆的View in Notepad 通过记事本打开. 可以使⽤ctrl+a全选左侧的抓包结果,delete键清除所有被选中的结果. 

1).抓包工具的原理

 抓包工具就是把获取的网络数据包的详细格式解析出来,抓包工具就相当于“代理”。

2).抓包结果

以下是⼀个HTTP请求/响应的抓包结果.

3).协议格式总结:

注:HTTP报⽂中要存在"空⾏",是因为HTTP协议并没有规定报头部分的键值对有多少个.空⾏就相当于是"报头的结束标记",或者是 "报头和正⽂之间的分隔符".HTTP在传输层依赖TCP议,TCP是⾯向字节流的.如果没有这个空⾏,就会出现"粘包问题".

4.HTTP各部分具体介绍

HTTP请求(request)

1.URL

URL基本格式:

以一个具体例子来说:

  • 协议名称,URL不是HTTP专属的概念,可以给各种协议提供支持。
  • :要访问的服务器的IP地址或域名,域名和IP可以相互转换,这个过程通过DNS域名解析系统来完成的(DNS即是一套服务器系统,也是一种应用层协议)。
  • :端口号,区分哪个应用程序。
  • :带有层次结构的路径,想要访问的是,某个主机上某个程序管理的某个资源(某个资源可以是一个硬盘上的文件,也可以是虚拟的资源)。
  • :查询字符串 Query String,对要访问的资源补充说明,也是键值对结构,键值对之间使用&分割,键和值之间使用=分割。
2.URL encode

像/?:等这样的字符,已经被url当做特殊意义理解了.因此这些字符不能随意出现. ⽐如,某个参数中需要带有这些特殊字符,就必须先对特殊字符进⾏转义.

注:⼀个中⽂字符由UTF-8或者GBK这样的编码⽅式构成,虽然在URL中没有特殊含义,但是仍然需要进 ⾏转义.否则浏览器可能把UTF-8/GBK编码中的某个字节当做URL中的特殊符号.

转义规则:将需要转码的字符转为16进制,然后从右到左,取4位(不⾜4位直接处理),每2位做 ⼀位,前⾯加上%,编码成%XY格式。

比如在这里“+”就被转义成“%2B”。

3.“认识”方法(method

1).GET方法

get最常用的是http方法,常用于获取服务器上的某个资源,在浏览器中直接输⼊URL,此时浏览器就会发送出⼀个GET请求. 另外,HTML中的link,img,script等标签,也会触发GET请求,使⽤JavaScript中的ajax也能构造GET请求。

get方法的特点:

  • ⾸⾏的第⼀部分为GET;
  •  URL的query string可以为空,也可以不为空 ;
  • header部分有若⼲个键值对结构;
  • body部分为空。
2).POST方法

post经常用于登录;或者上传,请求带有正文的(正文就是保存了当前上传的数据内容)。

post方法的特点:

  • ⾸⾏的第⼀部分为POST
  • URL的querystring⼀般为空(也可以不为空)
  •  header部分有若⼲个键值对结构
  •  body部分⼀般不为空.body内的数据格式通过header中的Content-Type 指定.body的⻓度 由header中的Content-Length 指定.

GET和POST的区别

  1. 语义上的区别。(语义上可以混着用,POST也是可以带有query string,GET理论上也可以带body,不过都比较少见)
  2. 携带数据的方式。

(GET和POST本质上没有区别,经常是能够混着用的,从使用方法习惯上来说,主要是两个方面的区别)

3.GET请求通常设计成幂等(请求一定的,得到的响应也是一定的)的,POST无要求。

4.GET设计成幂等的了,就可以允许GET请求的结果被缓存;POST由于不要求幂等,经常是不幂等的,就认为不能被缓从。

其他:

  • 关于安全性:有些资料上说"POST⽐GET安全".这样的说法是不科学的.是否安全取决于前端在 传输密码等敏感信息时是否进⾏加密,和GET 、POST⽆关,保证安全关键是“加密运输”。
  •  关于传输数据量:有的资料上说"GET传输的数据量⼩,POST传输数据量⼤".这个也是不科学的,标 准没有规定GET的URL的⻓度,也没有规定POST的body的⻓度.传输数据量多少,完全取决于不 同浏览器和不同服务器之间的实现区别.
  • 关于传输数据类型:有的资料上说"GET只能传输⽂本数据,POST可以传输⼆进制数据".这个也是 不科学的.GET的query string虽然⽆法直接传输⼆进制数据,但是可以针对⼆进制数据进⾏url encode.
4.认识请求“报头”(header)

header的整体的格式也是"键值对"结构. 每个键值对占⼀⾏.键和值之间使⽤分号分割.

4.1Host :表示服务器主机的地址和端口

HTTP协议中,传输的时候可能会涉及到“加密”(HTTPS),url部分是不会被加密的,被加密的是header和body。

4.2Content-Length:表示body中的数据长度,单位是字节

HTTP协议,传输层这里基于TCP实现的(版本号<=2.0),所谓的HTTP协议,就是把字符串构成HTTP约定的格式。

把这样一串字符串写入到tcp.socket中,对于TCP而言,一个连接上可以发送多个请求,服务器这边收到数据的时候就得区分一下,从哪里到哪里是一个完整的http请求数据,其中对没有body的http请求,读到空行,就可以认为是结束了,对于有body的http请求,先读取首行和header,读到空行解析header中的Content-Length,根据这里的取值,接下来再固定字节的长度。对于UDP而言,UDP面向数据报,读写的基本单位是一个数据报,某个应用层协议,基于UDP,一个UDP数据报就对应一个完整的应用层数据包,调用一次receive操作,就得到一个明确的UDP数据包。

4.3Content-Type:表⽰请求的body中的数据格式.

提示接收方如何解析body中的数据,HTTP这里面能够携带的数据种类是比较多。

例如:

4.4User-Agent(简称UA): 表⽰浏览器/操作系统的属性

比如:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)

说明: 其中Windows NT 10.0; Win64; x64 表⽰操作系统信息,AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 表⽰浏览器信息.

4.5Referer:描述了当前页面的来源,表⽰这个⻚⾯是从哪个⻚⾯跳转过来的

比如:

 如果直接在浏览器中输⼊URL,或者直接通过收藏夹访问⻚⾯时是没有Referer的.

4.6Cookie

 Cookie中存储了⼀个字符串,这个数据可能是客⼾端(⽹⻚)⾃⾏通过JS写⼊的,也可能来⾃于服务器 (服务器在HTTP响应的header中通过Set-Cookie字段给浏览器返回数据),往往可以通过这个字段实现"⾝份标识"的功能. 每个不同的域名下都可以有不同的Cookie,不同⽹站之的Cookie并不冲突.

Cookie就是浏览器允许网页在本地硬盘存储数据的一种机制,不是让网页代码直接访问文件系统,而是做了一次抽象,浏览器的Cookie提供了键值对存储机制。

浏览器保存了这些cookie之后,就会在后续给服务器发送请求的时候,把这些cookie键值对放到请求cookie header中传输给服务器。

cookie从服务器这边来的(由程序员决定),cookie最终发回给服务器。

Cookie里的数据都是程序员自定义的内容,但是有一个典型的场景,属于“通用业务”,就是登录和用户认证。

5. 认识请求“正文”(body)

正⽂中的内容格式和header中的Content-Type密切相关.上⾯也罗列了三种常⻅的情况

1)application/x-www-form-urlencoded2)multipart/form-dat3)application/json

HTTP响应

1.认识“状态码”

状态码表⽰访问⼀个⻚⾯的结果.(是访问成功,还是失败,还是其他的⼀些情况...).

以下是几种常见的状态码:

200 OK 这是⼀个最常⻅的状态码,表⽰访问成功.

比如访问搜狗界面,访问成功

404 Not Found 没有找到资源.

浏览器输⼊⼀个URL,⽬的就是为了访问对⽅服务器上的⼀个资源.如果这个URL标识的资源不存在,那么就会出现404。

比如输入一个错误的网址,www.sogou.com/index2.html,就会出现下面这种情况。

注:在抓包观察响应数据的时候,可能会看到压缩之后的数据,如图上最后一部分,这是⽹络传输中"带宽"是⼀个稀缺资源,为了传输效率更⾼往往会对数据进⾏压缩.点击Fiddler中的即可看到全部内容。

403 Forbidden 表⽰访问被拒绝.

有的⻚⾯通常需要⽤⼾具有⼀定的权限才能访问(登陆后才能访问).如果⽤⼾没有登陆 直接访问,就容易⻅到403.

405 Method Not Allowed 前⾯我们已经学习了HTTP中所⽀持的⽅法,有GET,POST,PUT,DELETE等.但是对⽅的服务器不⼀定都⽀持所有的⽅法(或者不允许⽤⼾使⽤⼀些其他的⽅法).

500 Internal Server Error 服务器出现内部错误.⼀般是服务器的代码执⾏过程中遇到了⼀些特殊情况(服务器异常崩溃)会产⽣这 个状态码.

504 Gateway Timeout 当服务器负载⽐较⼤的时候,服务器处理单条请求的时候消耗的时间就会很⻓,就可能会导致出现超时 的情况.

302 Move temporarily 临时重定向.

理解重定向:就相当于手机号码中的"呼叫转移"功能.比如我本来的手机号是 186-1234-5678,后来换了个新号码 135-1234-5678,那么不需要让我的朋友知道新号码,只要我去办理一个呼叫转移业务,其他人拨打 186-1234-5678,就会自动转移到 135-1234-5678上。

在登陆⻚⾯中经常会⻅到302.⽤于实现登陆成功后⾃动跳转到主⻚.

301 Moved Permanently 永久重定向.当浏览器收到这种响应时,后续的请求都会被⾃动改成新的地址.301也是通过Location字段来表⽰要重定向到的新地址.

状态码的小结:

2.认识响应"报头"(header) 

响应报头的基本格式和请求报头的格式基本一致.类似于 Content-Type,content-Length 等属性的含义也和请求中的含义一致
Content-Type
响应中的 Content-Type 常见取值有以下几种:

  • text/html:body数据格式是 HTML
  • text/css:body数据格式是CSS
  • application/javascript:body数据格式是 JavaScript
  • application/json:body数据格式是JSON
3.认识响应“正文”(body)

正⽂的具体格式取决于Content-Type.观察下面几个抓包结果中的响应部分。

1)text/html

2)text/css

3)application/javascript

4)application/json

构造HTTP请求

1.通过from表单构造HTTP请求

form(表单)是HTML中的⼀个常⽤标签.可以⽤于给服务器发送GET或者POST请求.

2.通过ajax构造HTTP请求

ajax全称Asynchronous Javascript AndXML,是2005年提出的⼀种JavaScript给服务器发送 HTTP请求的⽅式.特点是可以不需要刷新⻚⾯/⻚⾯跳转就能进⾏数据传输.

3.通过Java  socket构造HTTP请求

HTTP请求本质上就是TCP请求,只需要构造字符串,符合HTTP协议格式,写入到TCP socket中:所谓的"接受HTTP响应",本质上就是从TCP Socket中读取⼀个字符串,再按照HTTP的格式来解析.

4.通过postman这样的工具构造http请求

三、HTTPS

1.概念

HTTPS也是⼀个应⽤层协议.是在HTTP协议的基础上引⼊了⼀个加密层.HTTP协议内容都是按照⽂本的⽅式明⽂传输的.这就导致在传输过程中出现⼀些被篡改的情况.

HTTPS=HTTP+S(SSL/TLS),SSL也是一个应用层协议,专门负责加密。

我们网络传输的任何的任何数据包都会经过网络运营商的网络设备(路由器、交换机等),那么运营商的⽹ 络设备就可以解析出你传输的数据内容,并进⾏篡改.

举个例子,我们在下载软件时都会发生原本是要下一个QQ音乐,结果下载下来的是QQ浏览器,这就是“运营商劫持”,点击"下载按钮",其实就是在给服务器发送了⼀个HTTP请求,获取到的HTTP响应其实就包含了该 APP的下载链接.运营商劫持之后,就发现这个请求是要下载天天动听,那么就⾃动的把交给⽤⼾的响应 给篡改成"QQ浏览器"的下载地址了.

因为HTTP是明文传输的,所以很容易被运营商,黑客等通过类似的手段来获取信息,或者篡改内容,这是很危险的,所以我们使用HTTPS,HTTPS就是在HTTP的基础上进⾏了加密,进⼀步的来保证⽤⼾的信息安全。

2.如何理解HTTPS的加密

加密就是把明⽂(要传输的信息)进⾏⼀系列变换,⽣成密⽂.解密就是把密⽂再进⾏⼀系列变换,还原成明⽂.在这个加密和解密的过程中,往往需要⼀个或者多个中间的数据,辅助进⾏这个过程,这样的数据称为密 钥

3.HTTPS的工作过程

加密的方式有很多种,但主要分为两类:

  •  对称加密:加密和解密使用同一个密钥。运算速度快,开销小,适合针对大量数据进行加密。
  •  非对称加密:加密使用一个密钥,解密使用另一个密钥。运算速度慢,开销大,加密小的数据还行,加密大量数据非常耗时。
3.1引入对称加密

当我们引入对称密钥之后,即使数据被截获,由于黑客不知道密钥是什么,就无法对其破解,获得具体的内容。

但如果服务器给多个客户提供服务,而这多个客户端的密钥应该是不同的(如果是相同那密钥就太容易扩散了,⿊客就也能拿到了)。因此服务器就需要维护每个客⼾ 端和每个密钥之间的关联关系,⽐较理想的做法,就是能在客⼾端和服务器建⽴连接的时候,双⽅协商确定这次的密钥是什么。

但这样又会出现新的问题,此时密钥是明文传输的,那么黑客就很容易获得密钥了,那我们后面的加密就没用了,所以密钥也必须加密传输,但是要想对密钥进⾏对称加密,就仍然需要先协商确定⼀个"密钥的密钥".这就成了"先有鸡还是先有 蛋"的问题了.此时密钥的传输再⽤对称加密就⾏不通了. 就需要引⼊⾮对称加密.

3.2 引入非对称加密

⾮对称加密要⽤到两个密钥,⼀个叫做"公钥",⼀个叫做"私钥". 公钥和私钥是配对的.最⼤的缺点就是运算速度⾮常慢,⽐对称加密要慢很多.

• 客⼾端在本地⽣成对称密钥,通过公钥加密,发送给服务器

• 由于中间的⽹络设备没有私钥,即使截获了数据,也⽆法还原出内部的原⽂,也就⽆法获取到对称密 钥。

• 服务器通过私钥解密,还原出客⼾端发送的对称密钥.并且使⽤这个对称密钥加密给客⼾端返回的响 应数据.

• 后续客⼾端和服务器的通信都只⽤对称加密即可.由于该密钥只有客⼾端和服务器两个主机知道,其 他主机/设备不知道密钥即使截获数据也没有意义.

由于对称加密的效率⽐⾮对称加密⾼很多,因此只是在开始阶段协商密钥的时候使⽤⾮对称加密,后续 的传输仍然使⽤对称加密。

在这个场景下有三个密钥:客户端生成的对称密钥;服务器生成的公钥,可以给所有设备告知;服务器生成的密钥,只有自己知道。

中间人攻击

在上述流程中仍存在大量的安全隐患,黑客可以通过特殊手段,获取对称密钥,来破坏后续传输的安全性,⿊客可以使⽤中间⼈攻击,获取到对称密钥.那什么是中间人攻击?

中间人攻击:是一种网络攻击方式,攻击者在通信双方之间插入自己,并充当中间人,从而拦截、篡改或伪造通信内容。

以下面这个例子为例来讲述中间人攻击的大致流程:

相关说明:此时,服务器传过来公钥是pub1就会被黑客给拦截,改成了自己的公钥pub2,此时客户端用pub2来加密,因为客户端是是无法区分这个pub2的,只能选择使用pub2来加密。黑客就可以使用配对的pri2来解密,就可以拿到key,黑客继续使用服务器的pub1来对key重新加密,再传给服务器。服务器继续使用pri1解密,然后拿到key,后续客户端和服务器就会使用key来进行加密传输。

但此时,key已经被黑客获取,存在很大的安全隐患,那我们该如何解决这一问题呢?

3.3引入证书

引入校验和机制,是避免中间人攻击的关键,因为客户端无法区分收到的公钥是否是服务器真实的公钥还是被黑客篡改过的公钥,所以可以通过此方法可以对公钥是否正确进行校验。

服务端在使⽤HTTPS前,需要向CA机构申领⼀份数字证书,数字证书⾥含有证书申请者信息、公钥信 息、服务器域名等。服务器把证书传输给浏览器,浏览器从证书⾥获取公钥就⾏了,证书就如⾝份证,证明服务端 公钥的权威性。

以下是申请证书的一个流程图:

那引入证书后又是怎样操作的呢?

1.客户端收到证书的时候,要进行检验,针对证书中的其他字段(比如证书的机构,证书的有效期,服务器的公钥,服务器的域名等),使用同样的算法,再算一次校验和,得到校验和1(校验和1针对客户端收到的数据进行计算的)。

2.通过公正机构的公钥pub2,对数字签名进行解密,得到校验和2(服务器申请证书的时候得到的原始校验和)。

数字签名:本质上是一个被加密的校验和(把要检验的数据带入一个固定的公式算出的一个数字)。

那客户端如何确保拿到的公钥pub2是公正机构的pub2,而不是黑客伪造的呢?因为这个pub2不是通过网络传输的,而是操作系统内置的,安装好系统,系统就内置了一系列知名公正机构的公钥,这些pub2就是正确合法的。

3.对比校验和1和校验和2是否相同,如果相同,说明证书没被修改过,客户端收到的数据是原始数据,如果不同,证书无效,中间被人篡改过。

如果此时黑客想要直接修改证书中的公钥为自己的公钥,此时客户端计算的校验和解密出来的原始校验和就对不上了,客户端此时就会报错,浏览器就会出现一个红色的界面,提示你该网站不安全,是否继续访问。

总结:

  • 引入证书是为了防止黑客修改公钥,黑客可以看到公钥的内容,但不能修改,所以无所谓,整个过程只是为了保证客户端可以验证公钥是合法的,只要公钥的合法性验证通过,后续客户端继续使用公钥对对称密钥加密和传输。
  • 服务器的域名是唯一的,黑客自己申请一个证书来替换服务器的证书,因为黑客申请的正书的域名与服务器域名是不同的。

四、总结

完整流程

左侧都是客户端做的事,右侧都是服务器做的事。

HTTPS⼯作过程中涉及到的密钥有三组。

  •  第⼀组(⾮对称加密):⽤于校验证书是否被篡改.服务器持有私钥(私钥在注册证书时获得),客⼾端持有 公钥(操作系统包含了可信任的CA认证机构有哪些,同时持有对应的公钥).服务器使⽤这个私钥对证书 的签名进⾏加密.客⼾端通过这个公钥解密获取到证书的签名,从⽽校验证书内容是否是篡改过.
  •  第⼆组(⾮对称加密):⽤于协商⽣成对称加密的密钥.服务器⽣成这组私钥-公钥对,然后通过证书把公 钥传递给客⼾端.然后客⼾端⽤这个公钥给⽣成的对称加密的密钥加密,传输给服务器,服务器通过私钥 解密获取到对称加密密钥. 
  • 第三组(对称加密):客⼾端和服务器后续传输的数据都通过这个对称密钥加密解密.其实⼀切的关键都是围绕这个对称加密的密钥.其他的机制都是辅助这个密钥⼯作的. 第⼆组⾮对称加密的密钥是为了让客⼾端把这个对称密钥传给服务器. 第⼀组⾮对称加密的密钥是为了让客⼾端拿到第⼆组⾮对称加密的公钥.