HTTP连接效率
HTTP是请求应答模式,每次都会先和服务器建立连接三次握手,然后收到响应之后会关闭连接四次挥手。这个连接过程很短暂又称为短连接,相当于重复的开启关闭步骤这样非常消耗时间。
针对这个缺点,出现了长连接的方式,就是打开连接之后不会立马关闭,而是等执行完操作或者等待一定时间才关闭。关于连接的相关字段是告诉服务器这是一个长连接
Connetion:Keep-Alive
但是长连接一直不关闭也会消耗服务器资源,因此可以使用
- 使用“keepalive_timeout”指令,设置长连接的超时时间,如果在一段时间内连接上没有任何数据收发就主动断开连接,避免空闲连接占用系统资源。
- 使用“keepalive_requests”指令,设置长连接上可发送的最大请求次数。比如设置成1000,那么当Nginx在这个连接上处理了1000个请求后,也会主动断开连接。
HTTP响应码
服务器收到请求报文,解析后需要进行处理,最后是拼出一个响应报文发回客户端。
响应报文由响应头加响应体数据组成,响应头又由状态行和头字段构成,状态码的意义在于用于表达HTTP数据处理的状态
- 1××:提示信息,表示目前是协议处理的中间状态,还需要后续的操作;
- 2××:成功,报文已经收到并被正确处理;
- 200:请求成功,响应头后有body数据
- 204:请求成功,响应头后没有body数据
- 3××:重定向,资源位置发生变动,需要客户端重新发送请求;
- 301:永久重定向,说明请求的资源已经不存在了,需改⽤新的 URL 再次访问
- 302:临时重定向,资源还在,暂时需要⽤另⼀个 URL 来访问
- 304:表示资源未修改,定向已存在的缓冲⽂件,也称缓存᯿定向,⽤于缓
存控制
- 4××:客户端错误,请求报文有误,服务器无法处理;
- 400:通用的错误码,表示请求报文有错误
- 403:表示服务器禁止访问资源
- 404:找不到资源
- 405:不允许使用某些方法操作资源,例如不允许POST只能GET
- 5××:服务器错误,服务器在处理请求时内部发生了错误
- 500:通用的错误码
- 502:服务器作为网关或者代理时返回的错误码,
- 503:超时响应
HTTP转发和重定向
浏览网站的时候经常有各种链接,我们点击这个链接就会跳转到另一个页面,这个行为是我们主动控制触发,却是服务器控制的它去请求这个URL然后返回数据,也叫跳转(Forward)
但是还有一种不是我们能够控制的,是服务器主动控制的,客户端去请求那个URL,URL地址栏会变,这个叫重定向(Redirect)
直接转发 Forward 就相当于:“A找B借钱,B说没有,然后B去找C借,借到借不到都会把消息传递给A”;
间接转发 Redirect 就相当于:"A找B借钱,B说没有,让A去找C借"。
forward:一般用于用户登陆的时候,根据角色转发到相应的模块 redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等
HTTP缓存
浏览器使用HTTP获取资源的成本较高,有必要把来之不易的数据缓存起来,缓存的流程是
- 浏览器发现缓存无数据,于是发送请求,向服务器获取资源;
- 服务器响应请求,返回资源,同时标记资源的有效期;
- 浏览器缓存资源,等待下次重用
Cache-Control:max-age=30
这个max-age表示从创建这个响应报文,整个缓存的生存时间
HTTP缓存有几种不同的缓存类型
no_store
:不允许缓存,用于某些变化非常频繁的数据,例如秒杀页面;no_cache
:它的字面含义容易与no_store搞混,实际的意思并不是不允许缓存,而是可以缓存,但在使用之前必须要去服务器验证是否过期,是否有最新的版本;must-revalidate
:又是一个和no_cache相似的词,它的意思是如果缓存不过期就可以继续使用,但过期了如果还想用就必须去服务器验证。
Last-modified
:就是文件的最后修改时间。
真正使用到缓存就是在前进后退的时候,这个时候不会发送新的请求,不再进行网络通讯,这个实现的原理就是
HTTP协议定义了一系列“If”开头的“条件请求”字段,专门用来检查验证资源是否过期,最常用的是if-Modified-Since
和If-None-Match
这两个,有两种不同条件搭配使用
- 第一次响应报文提供
ETag
,第二次请求时就可以发出If-None-Match
带上缓存里的原值,验证资源是否是最新的,资源没有变就返回一个304,表示缓存依然有效 - 第一次响应报文提供
Last-modified
,第二次请求时就可以发出If-Modified-Since
带上缓存里的原值,验证资源是否是最新的
ETag是“实体标签”(EntityTag)的缩写,是资源的一个唯一标识,主要是用来解决修改时间无法准确区分文件变化的问题,ETag就可以精确地识别资源的变动情况,让浏览器能够更有效地利用缓存。
强ETag要求资源在字节级别必须完全相符,弱ETag在值前有个“W/”标记,只要求资源在语义上没有变化,但内部可能会有部分发生了改变
HTTP的Cookie机制
HTTP是无状态的,意味着每个请求都是独立的,也无法知道前面的信息,也无法纪录信息,但有的场景交互是需要承前启后的,两种用于保持 HTTP 连接状态的技术就应运而生了,一个是 Cookie,而另一个则是 Session。
Cookie是服务器用于标记客户端的,让服务器记住不同的客户端身份,用户第一次访问浏览器,服务器不知道它的身份,因此会在头部放置一个Set-Cookie,里面可以放置多个值,但大小也是有限制的。
请求头:
Set-Cookie:tst=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=.zhihu.com; httponly
响应头:
Cookie: tst=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=.zhihu.com; httponly
Cookie其他属性
- Expires:过期时间,可以理解为“截止日期
- Max-Age:相对时间,多少秒以后过期。Max-Age优先级更高,会先采用Max-Age
- Domain:Cookie的作用域,让浏览器仅发送给特定的服务器和URI,避免被其他网站盗用
- Path:Cookie所属的路径
- HttpOnly:保证Cookie的安全性,Cookie只能通过浏览器HTTP协议传输,禁止其他方式访问
- SameSite:防范“跨站请求伪造”(XSRF)攻击,可以严格限定Cookie不能随着跳转链接跨站发送
- Secure:这个Cookie仅能用HTTPS协议加密传输,明文的HTTP协议会禁止发送。但Cookie本身不是加密的,浏览器里还是以明文的形式存在
Cookie的作用
- 有状态的会话事务和身份识别:可以保持登录状态免登录,还可以作为身份标识
- 广告跟踪:其他网站给你贴小标签,存储在它们的Cookie中,也叫第三方Cookie,上其他的网站,别的广告就能用Cookie读出你的身份,然后做行为分析,再推给你广告
HTTP字段
Host
:指定服务器域名,例如Host: gitee.com
Content-Length
:表明返回body数据的长度,Content-Length: 1000
Connetion
:要求服务器使用持久连接,Connection: keep-alive
Content-Type
:用于服务器响应的时候告诉客户端是什么格式的数据,一般是 Content-Type: text/html; charset=utf-8
Content-Encoding
:说明字段的压缩方式,例如Accept-Encoding: gzip, deflate
User-Agent
:是请求字段,描述发起HTTP请求的客户端
HTTP代理
HTTP协议中有两个角色,请求方和应答方,现在还有一个角色就是HTTP代理,代理服务本身不生产内容,而是处于中间位置转发上下游的请求和响应
代理服务的作用
那么这个代理的作用是什么呢?因为代理是中间角色,所以两边客户端和服务器都不知道对方是具体是谁,又可以分为正向代理和反向代理
正向代理是代理客户端向服务器发送消息,例如我们想去访问国外网站无法直接访问,需要通过代理服务器帮我们和目标服务器进行交互,目标服务器不知道真正的访问要访问的是谁
正向代理的主要作用就是突破访问限制、隐藏客户端、提高访问速度
反向代理是代理服务器向客户端发送消息,例如在一线城市租房经常会遇到二房东,所谓二房东就是自己在很多真正的房东那里把房子承包下来,然后租给租户,但租户根本不知道真正的房东是谁。
反向代理可以用来负载均衡、隐藏服务器、提供安全保障
HTTP中代理需要使用Via
字段表明代理身份,每经过一个代理节点就会在字段里面增加一个代理人,但是也不清楚客户端的信息。
通常服务器需要知道客户端的真实IP地址,最常用的两个头字段是“X-Forwarded-For”和“X-Real-IP”分别表示为谁转发还有客户端的IP地址
HTTP缓存代理
HTTP代理只是一个中转的作用,但是对于那种读多写少的数据,一秒钟成千上万次的请求,如果缓存几秒钟的的数据就可以降低服务器的压力。
在HTTP中,HTTP缓存代理很特殊既是服务器也可以是客户端,HTTP本身也有缓存属性,为了区分HTTP缓存代理使用了新的属性:private
、public
private表示缓存只能在客户端保存,是用户“私有”的,不能放在代理上与别人共享。而“public”的意思就是缓存完全开放,谁都可以存,谁都可以用。
HTTPS相关概念
HTTP整个传输过程完全透明,任何人都能够在链路中截获、修改或者伪造请求/响应报文,数据不具有可信性。这样对于银行、购物、个人信息等等数据都不安全
HTTPS在 HTTP 与 TCP 层之间加⼊了 SSL/TLS 协议,可以很好的解决了上述的⻛险,默认端口号是443,请求-应答模式、报文结构、请求方法、URI、头字段、连接管理等等都完全沿用HTTP,但是HTTPS增加了四大安全特性,分别是:
- 机密性(Secrecy/Confidentiality):只有可信的人才能访问
- 完整性(Integrity):传输过程中没有被窜改
- 身份认证(Authentication):确认对方的真实身份
- 不可否认(Non-repudiation/Undeniable):发生的传输行为不可抵赖
保障安全的秘密就是这个名字里的“s”,它代表SSL/TLS协议,把HTTP下层的传输协议由TCP/IP换成了SSL/TLS
SSL/TLS
SSL即安全套接层(Secure Sockets Layer),在OSI模型中处于第5层(会话层),有v2和v3两个稳定的版本,在V3时被改名TSL(传输层安全,Transport Layer Security),所以TLS1.0实际上就是SSLv3.1。
目前应用的最广泛的TLS是1.2,TLS由记录协议、握手协议、警告协议、变更密码规范协议、扩展协议等几个子协议组成,综合使用了对称加密、非对称加密、身份认证等许多密码学前沿技术,浏览器在使用TSL建立连接的时候会使用一套合适的加密算法,会有一串很长的字符:ECDHE-RSA-AES256-GCM-SHA384,基本的形式是:密钥交换算法+签名算法+对称加密算法+摘要算法。
对称加密与非对称加密
对称加密:加密和解密时使用的密钥都是同一个,没有密钥无法解密,常用的有:AES
、ChaCha20
,运算速度快
非对称加密:有一个公钥和私钥,公钥是公开的,私钥是保密的,公钥加密后只能用私钥解密,反过来,私钥加密后也只能用公钥解密,有几种:DH
、DSA
、RSA
、ECC
,但速度慢
把对称加密和非对称加密结合起来就得到了又好又快的混合加密,也就是HTTPS里使用的加密方式
HTTPS保障通讯安全的原理
1、混合加密
通信刚开始的时候使用非对称算法,比如RSA、ECDHE,首先解决密钥交换的问题
用随机数产生对称算法使用的会话密钥,再用公钥加密
2、摘要算法
常见摘要算法有:MD5(Message-Digest5)、SHA-1(SecureHashAlgorithm1),但是不够安全,推荐使用SHA-2
SHA-2实际上是一系列摘要算法的统称,总共有6种,常用的有SHA224、SHA256、SHA384,分别能够生成28字节、32字节、48字节的摘要
例如:客户端在发送前通过SHA256加密传输内容,把传输内容和通过摘要算法加密后的传输内容一起发送,再通过会话密钥加密成密文发送给服务器,服务器解密成明文,然后服务器也用SHA256算出加密后的传输内容和摘要算法加密后的传输内容进行对比,说明数据是完整的
客户端发送的时候把「摘要 + 明⽂」⼀同加密成密⽂后,发送给服务器,服务器解密后,⽤相同的摘要算法算出发送过来的明文,然后对比
3、数字证书
私钥可以保证安全性,但是公钥却缺少防伪手段,这时候出现了CA(CertificateAuthority,证书认证机构)。它就像网络世界里的公安局、教育部、公证中心,具有极高的可信度,由它来给各个公钥签名,用自身的信誉来保证公钥无法伪造,是可信的。它包含序列号、用途、颁发者、有效时间等等,把这些打成一个包再签名,形成数字证书。作为信任链的源头CA有时也会不可信,解决办法有CRL、OCSP,还有终止信任。
HTTPS协议基本流程及优化
前面说到HTTPS是 HTTP 与 TCP 层之间加⼊了 SSL/TLS 协议,TCP层之间有三次握手四次挥手,加上SSL/TLS 的握⼿涉及四次通信,总共是11次。
SSL/TLS 协议基本流程:
- 客户端向服务器发起加密通信请求包括:客户端⽀持的 SSL/TLS 协议版本、客户端⽣产的随机数、客户端⽀持的密码套件列表(生成会话密钥)
- 服务器收到客户端请求后,向客户端发出响应:确认 SSL/ TLS 协议版本、服务器⽣产的随机数、确认的密码套件列表、服务器的数字证书
- 客户端回应:查看CA 公钥确认服务器的数字证书的真实性、取出服务器的公钥然后使⽤它加密报⽂、产生第三个随机数
- 服务器的最后回应:查看第三个随机数通过加密算法计算会话秘钥,服务器握⼿结束通知,表示服务器的握⼿阶段已经结束
HTTPS优化
HTTPS慢的原因是多了SSL/TLS 的握⼿涉及四次通信,这里面又包含建立连接时的非对称加密握手,第二个是握手后的对称加密报文传输、获取CA证书等等一些网络耗时,主要优化是根据软件优化:
- 采用新版本的协议
- 使用更快的加密解密算法
- 使用证书优化
- 会话复用,一次建立连接多次通讯
HTTP面试题
GET和POST的区别
1.GET是从服务器请求资源,一般是静态文本、图片、视频等等,POST则是提交数据,提交内容放在Body里面
2.GET是不安全的请求url有长度限制2048byte(2kb),post对把请求参数放在请求体里面长度没有限制
3.GET请求在回退时是无害的,而post请求在回退时会被再重新执行一次
4.GET请求的静态资源会被缓存,而post请求不会被缓存
HTTP特性
优点
最大的优点是简单、灵活和易于扩展;
拥有成熟的软硬件环境,应用的非常广泛,是互联网的基础设施;
是无状态的,可以轻松实现集群化,扩展性能,
缺点
是明文传输,数据完全肉眼可见,能够方便地研究分析,但也容易被窃听,不安全
是不安全的,无法验证通信双方的身份,也不能判断报文是否被窜改;
性能不算差,但不完全适应现在的互联网,还有很大的提升空间。
为什么HTTP是无状态协议
HTTP对用户的操作没有记忆力,每个请求都是完全独立的,每个请求包含了处理这个请求所需的完整的数据,发送请求不涉及到状态变更,因此我们登录之后再次就可以免登录不是HTTP的作用,而是Cookie机制,让浏览器具有记忆力。
Cookie
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就向客户端浏览器颁发一个Cookie。客户端会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容
如果不设置过期时间那么浏览器关闭就会消失,如果设置过期时间那么关闭浏览器直到在设定有效期内都有效
但是服务端无法识别具体是哪个客户端发来的信息
Session
Session保存在服务器上,客户端请求服务器后,服务器都会建立一个session并自动分配一个SessionId,用于标识用户的唯一身份,当客户端浏览器再次访问时只需要从该Session中查找该用户的状态
有了Cookie和Session就可以识别身份了,比如:有很多人来了我家里喝茶,但是我都不认识那些人。假如我给来喝茶的人颁发一个序号,那么当他下次来喝茶我就知道这个人之前来过是老朋友了
Cookie 和 Session 有什么不同
- 作用范围不同,Cookie 保存在客户端(浏览器),Session 保存在服务器端。
- 存取方式的不同,Cookie 只能保存 ASCII,Session 可以存任意数据类型,一般情况下我们可以在 Session 中保持一些常用变量信息,比如说 UserId 等。
- 有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。
- 隐私策略不同,Cookie 存储在客户端,比较容易遭到不法获取,早期有人将用户的登录名和密码存储在 Cookie 中导致信息被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。
- 存储大小不同, 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie。
浏览器中禁止了 Cookie怎么办?
第一种方案,每次请求中都携带一个 SessionID 的参数,也可以 Post 的方式提交,也可以在请求的地址后面拼接 ?SessionID=XXX
第二种方案,Token 机制。Token 机制多用于 App 客户端和服务器交互的模式,也可以用于 Web 端做用户状态管理。
如何解决跨域请求?Jsonp 跨域的原理是什么?
说起跨域请求,必须要了解浏览器的同源策略,同源策略/SOP(Same origin policy)是一种约定,由 Netscape 公司 1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS、CSFR 等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源。
解决跨域请求的常用方法是:
- 通过代理来避免,比如使用 Nginx 在后端转发请求,避免了前端出现跨域的问题。
- 通过 Jsonp 跨域
- 其它跨域解决方案:Cron
地址栏输入URL发生了什么
- 首先浏览器会根据输入URL地址,去找本地是否被DNS缓存,有的话直接返回IP,假如没有回查询本机的host文件是否有配置IP地址
- 如果也没有那就直接向网络中发起一个DNS查询,通过DNS根域名服务器->顶级域名服务器->权威DNS服务器获取到域名对应的IP
- 浏览器需要和目标地址进行TCP连接,经过三次握手
- 浏览器向服务器发送请求,服务器响应请求,然后就会进行四次挥手关闭连接
参考资料:
罗剑锋.透视HTTP协议.极客时间
小林Coding-图解网络