http
http(n)
1. http/1.x
- 缺陷:线程阻塞,在同一时间,同一域名下面的请求有一定的数量限制,超过限制数目的请求会被阻塞
(1). http1.0
-
缺陷:浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP(TCP连接的新建成本很高,因为需要客户端和服务器三次握手),服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求
-
解决方案:添加头部信息----非标准的Connection字段
Connection:keep-alive
(2). http1.1
- 针对与http1.0的改进点
-
持久连接:引入了持久连接,即TCP连接默认不关闭,可以被多个请求复用,不用声明
Connection:keep-alive(对于同一个域名,大多数浏览器允许同事建立6个持久连接) -
管道机制:即在同一个TCP连接里面,客户端可以同时发送多个请求
-
分块传输编码:即服务端每产生一块数据,就发送一块,采用“流模式”而取代“缓存模式”
-
新增请求方式
-
PUT:请求服务器存储一个资源;
-
DELETE:请求服务器删除标识的资源;
-
OPTIONS:请求查询服务器的性能,或者查询与资源相关的选项和需求;
-
TRACE:请求服务器回送收到的请求信息,主要用于测试或诊断;
-
CONNECT:保留将来使用
-
缺点: 虽然允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信式按次序进行的。服务端只有处理完一个请求,才会处理下一个请求,如果前面的处理特别慢,后面的就会又许多的请求排队等着,这就将导致“队阻塞”
-
避免方式: 一是减少请求数,二是同时多开持久连接
2. http/2.0
-
特点
-
采用二进制格式而非文本格式
-
完全多路复用,而非有序并阻塞的、只需一个链接即可实现运行
-
使用报头压缩,减低开销
-
服务器推送
-
- 二进制协议
-
- http/1.1版的头信息肯定是文本(ASCLL编码),数据体可以是文本,也可以是二进制。http/2则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为“帧”:头信息帧和数据帧
-
- 二进制协议解析起来更高效、“线上”更紧凑,更重要的是错误更少
- 完全多路复用
-
- http/2复用TCP连接,在一个连接里,客户端和浏览器端都可以同时发送多个请求或者回应,而不用按照顺序一一对应,这样就避免了“队头阻塞”
- 报头压缩
-
- http协议是没有状态,导致每次请求都必须附上所有信息,所以去,请求的很多头字段都是重复的,比如cookie,一样的内容每次请求的时候都必须带上,这样会浪费很多带宽,也影响速度
-
- 对于相同的头部,不必再通过请求发送,只需要发送一次
-
- http/2对这一点做了优化,引入了头部信息压缩机制
-
- 一方面,头信息使用gzip或compress压缩后再发送
-
- 另一方面,客户端和服务器同时维护一张头信息表,所有头信息表,所有字段都会存入这个表,产生一个索引号,之后就不发送同样字段了,只需要发送索引号
- 服务器推送
-
- http/2允许服务器未经请求,主动向客户发送资源
-
- 通过推送那些服务器任务客户端将会需要的内容到客户端的缓存中,避免往返的延迟
3. https
http协议通常承载于TCP协议之上,在http和TCP之间添加一个安全协议层(SSL和TSL),这个时候,就成了我们说的https
- https主要作用
-
- 对数据进行加密,并建立一个信息安全通道,来保证传输过程中的数据安全
-
- 对网站服务器进行真实身份认证
- http和https的区别
-
- https是加密传输协议,http是名文传输协议
-
- https需要用到SSL证书,而http不用
-
- https比http更加安全对搜索引擎更友好,利于SEO
-
- https标准端口,http标准端口80
- 5.http基于传输层,http基于应用层
- http和https的工作过程的区别
- http包含的动作:
浏览器打开一个TCP连接
浏览器发送HTTP请求到服务器
服务器发送HTTP回应到浏览器
TCP关闭
- SSL包含动作(https多http的一部分)
验证服务端
客户端和服务端选择加密算法和密码,确保双方都支持
验证客户端(可选)
使用公钥加密技术来生成加密数据
创建一个加密的SSL连接
基于上面的SSL连接传递HTTP请求
- https的加密方式
-
对称加密:加密和解密都是用的同一个密钥
-
非对称加密:加密和解密使用的密钥是不同的,分别成为:公钥、私钥;公钥和算法都是分开的,私钥是保密的
- 非堆成加密过程:服务端生成配对的公钥和私钥
- 私钥保存在服务端,公钥发送到客户端
- 客户端使用公钥加密明文传输到服务端
- 服务端使用私钥解密密文得到名文
-
数字签名:就是在信息的后面再加上一段内容,可以证明信息没有被修改过
TCP
1. 建立连接协议(三次握手)
- 第一次握手是客户端发送一个带 SYN 标志的 TCP 报文 1。
- 第二次是服务器端回应客户端,这是三次握手中的第 2 个报文,这个报文同时带 ACK 标志和 SYN 标志。它表示对刚才客户端 SYN 报文的回应,同时又标志 SYN 给客户端,询问客户端是否准备好进行数据通讯。
- 第三次是客户端必须再次回应服务端一个 ACK 报文。
2. 为什么需要三次握手
当 client 发出的第一个连接请求报文段 SYN 并没有丢失,而是在某个网络节点长时间的滞留,以导致延误时间释放以后的某个时间才到达 server。时间一过,这个报文段是已经失效的。
但是 server 收到此失效的连接报文段后,就会以为是 client 再次发出了一个新的连接请求,于是就向 client 发出确认报文段 ACK 和 SYN,同意建立连接。
加入不采取‘三次握手’,只要 server 发出确认,新的连接就建立了。由于现在 client 并没有发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的运输连接已经建立,并一直等待 client 发来数据。这样,server 的很多资源就白白浪费掉了。
采用‘三次握手’就可以防止上述现象发生。例如刚才那种情况,client 不会向 server 的确认发出确认,server 由于收不到确认,就知道 client 并没有要求建立连接。主要目的是防止 server 一直等待,浪费资源。
3. 连接终止协议(四次挥手)
- 第一次是 TCP 客户端发送一个 FIN,用来关闭客户到服务器的数据传送(报文段 4)
- 第二次是服务器收到这个 FIN 后,它发回一个 ACK,确认序号为收到的序号加 1(报文段 5)。和 SYN 一样,一个 FIN 将占有一个序号。
- 第三次是服务器关闭客户端的连接,发送一个 FIN 给客户端(报文段 6)。
- 第四次客户端发回 ACK 报文确认,并将确认序号设置为收到序号家 1(报文段 7)。
4. 为什么需要四次挥手
前面连接也只有三次,为什么服务器在收到客户端的 FIN 后,不一起发送 ACK 和 FIN 呢?
答:原因是因为 tcp 是全双工模式,server 接受到 FIN 时意味将没有数据再发来,但是还是可以继续发送数据。 什么是 tcp 全双工?
就是 client 和 server 都可以接收和发送数据,当 server 接受到 FIN 是 sever 可能不会立即关闭 socket,所以只能先回复一个 ACK 报文,告诉 client,你发的 FIN 报文我收到了。只有等 server 所有的报文都发送完了,server 才发生 FIN 报文,因此不能一起发送,所以需要四步挥手。
JWT
1. 跨域身份验证
Internet 服务无法与用户身份验证分开,一般过程如下
- 用户向服务端发送用户名和密码
- 验证服务器后,相关数据(如用户角色,登录时间等)将保存在当前会话中
- 服务器向用户返回 session_id,session 信息都会写入到用户的 Cookie
- 用户的每个后续请求都将通过在 cookie 中取出 session_id 传给服务器。
- 服务器收到 session_id 并对比之前保存的数据,确认用户的身份
这种模式最大的问题是,没有分布式架构,无法支持很想发展,如果使用一个服务器,该模式完全没有问题。但是如果他是服务器群集活面向服务的跨域体系结构的话,则需要一个统一的 session 数据库来保存会话数据实现共享,这样负载均衡下的每个服务器才可以正确的验证身份。
eg: 常见的单点登陆需求,站点 A 和站点 B 提供同一公司的相关服务。现在要求是用户只需要登陆其中一个网站,然后他就会自动登陆到另一个网站,怎么做?
一种解决方案是持续化 session 数据,写入数据库或文件持久层等,收到请求后,验证服务从持久层请求数据,该解决方案的有点在于架构清晰,但是缺点是架构修改比较麻烦,整个服务的验证逻辑层都需要重写,工作量大,而且由于依赖于持久层的数据库或者问题系统,会有单点风险,如果持久层失败,整个认证体系都会挂掉
2. JWT 原则
jwt 的原则是在服务器生粉验证之后,将生成一个 JSON 对象并将其发送回用户,如下所示:
{
"UserName": "xuanliao",
"Role": "admin",
"Expire": "2019-10-11 11:42:56"
}
之后,当用户于服务器通时,客户在请求中发回 JSON 对象。服务器仅依赖这个 JSON 对象来表示用户,为了防止用户篡改数据,服务器将在生成是添加签名
3. JWT 的数据结构
典型的 jwt 如下图
分为三个部分
- jwt 头
- 有效荷载
- 签名
3.1 JWT 头
JWT 头部分是一个描述 JWT 元数据的 JSON 对象,通常如下所示
{
"alg": "HS256",
"typ": "JWT"
}
从上面知道,alg 属性表示签名使用的算法,默认的是 HMAC SHA256(写为 HS256);typ 属性表示令牌的类型,JWT 令牌统一写为 JWT。
3.2 有效荷载
有效荷载部分是 JWT 的肢体部分,也是 json 对象,包含需要传递的数据。JWT 指定七个默认字段供选择
iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID 用于标识该 JWT
除了着 7 个值还可以自定义私有字段
{
"sub": "1234567890",
"name": "xuanliao",
"admin": true
}
请注意,默认情况下 JWT 是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。
JSON 对象也使用 Base64 URL 算法转换为字符串保存。
3.3 哈希签名
签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。
首先,需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用标头中指定的签名算法(默认情况下为 HMAC SHA256)根据以下公式生成签名。
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)
在计算出签名哈希后,JWT 头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用"."分隔,就构成整个 JWT 对象。
3.4 Base64URL 算法
如前所述,JWT 头和有效载荷序列化的算法都用到了 Base64URL。该算法和常见 Base64 算法类似,稍有差别。
作为令牌的 JWT 可以放在 URL 中(例如 api.example/?token=xxx)。 Base64 中用的三个字符是"+","/"和"=",由于在 URL 中有特殊含义,因此 Base64URL 中对他们做了替换:"="去掉,"+"用"-"替换,"/"用"_"替换,这就是 Base64URL 算法,很简单把。
4. JWT 的用法
客户端接收服务器返回的 JWT,将其存储在 Cookie 或 localStorage 中。
此后,客户端将在与服务器交互中都会带 JWT。如果将它存储在 Cookie 中,就可以自动发送,但是不会跨域,因此一般是将它放入 HTTP 请求的 Header Authorization 字段中。
Authorization: Bearer
当跨域时,也可以将 JWT 被放置于 POST 请求的数据主体中。
5. JWT 问题和趋势
1、JWT 默认不加密,但可以加密。生成原始令牌后,可以使用改令牌再次对其进行加密。
2、当 JWT 未加密方法是,一些私密数据无法通过 JWT 传输。
3、JWT 不仅可用于认证,还可用于信息交换。善用 JWT 有助于减少服务器请求数据库的次数。
4、JWT 的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限。也就是说,一旦 JWT 签发,在有效期内将会一直有效。
5、JWT 本身包含认证信息,因此一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT 的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行进行身份验证。
6、为了减少盗用和窃取,JWT 不建议使用 HTTP 协议来传输代码,而是使用加密的 HTTPS 协议进行传输。
http code
| 状态 | 类别 | 原因 |
|---|---|---|
| 1XX | Informational(信息性状态码) | 接收的请求正在处理 |
| 2XX | Success(成功状态码) | 请求正常处理完毕 |
| 3XX | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
| 4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
| 5XX | Server Error(服务器错误状态码) | 服务器处理请求错误 |
2XX
200 OK 成功
204 No Content 该状态码代表服务器接收的请求已经成功处理,但在返回的响应报文中不含实体的主体部分。另外,也不允许返回任何实体的内容。
206 Partial Content 该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求。
3XX
301 Moved Permanently 永久重定向。该状态码表示请求的资源已经被分配了新的URI,以后应该使用资源现在所指的URI。
302 Found 临时性重定向。该状态码表示请求的资源已经分配了新的URI,希望用户(本次)能使用新的URI访问。
304 Not Modified 该状态码表示客户端发送附带条件的请求时,服务器允许请求访问资源,但因为请求未满足条件的情况后,直接返回304(服务器端资源未改变,可直接使用客户端未过期的缓存)。
4XX
400 Bad Request 该状态码表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再发送请求。
401 Unauthorized 未授权,表示发送的请求需要通过认证。
403 Forbidden 该状态码表明对请求资源的访问被服务器拒绝了。
404 Not Found 服务器没有请求的资源。
5XX
500 Internal Server Error 服务器在执行请求时发生了错误。
503 Service Unavailable 表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
之前读过一篇文章,讲状态码讲的挺好的链接
浏览器缓存
浏览器的缓存机制也就是我们说的 HTTP 缓存机制,其机制是根据 HTTP 抱文的缓存标识进行的,HTTP 抱文分为两种:
- HTTP 请求(Request)抱文
- HTTP 响应(Response)抱文
浏览器与服务器通信的方式为应答模式,即为:浏览器发起 HTTP 请求 – 服务器响应该请求,那么浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中 HTTP 头的缓存标识,决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存中
- 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
- 浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中
缓存分为强制缓存和协商缓存
-
强制缓存
- HTTP 响应报文中的 expires--
expires: Wed, 21 Oct 2020 03:25:41 GMT,这个是一个绝对时间,在指定的时间前请求缓存生效 - HTTP 响应报文中的 Cache-Control--
cache-control: max-age=600,这是一个相对值,单位 s,也就是 600s 之内再次请求会直接使用缓存,强制缓存生效在无法确定客户端的时间是否与服务端的时间同步的情况下,Cache-Control 相比于 expires 是更好的选择,所以同时存在时,只有 Cache-Control 生效
强制缓存的返回状态码为: 200
但是看返回值中的 size 栏中有
from memory cache和from disk cache:分别是内存中的缓存和硬盘中的缓存,浏览器对与两者的读取顺序是: memory -> disk-
内存缓存:快速读取(直接写入进程的内存中,方便下次使用和快速读取)和时效性(也就是一旦关闭进程关闭,内存就会清空)
-
直接将缓存写入硬盘文件中,读取缓存需要对硬盘文件进行 I/O 操作,读取是复杂的,速度也是比内存慢的
- HTTP 响应报文中的 expires--
-
协商缓存(协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程)
- 协商缓存生效,返回 304
- 协商缓存失效,返回 200 和请求结果结果
协商缓存的表示在响应的报文中为:Last-Modified / If-Modified-Since 和 Etag / If-None-Match, 其中 Etag / If-None-Match > Last-Modified / If-Modified-Since
- 也就是说: 强制缓存优先于协商缓存进行,若强制缓存(Expires 和 Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since 和 Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回 304,继续使用缓存