HTTP
HTTP是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。
# HTTP特点
HTTP协议本身是无连接的,也就是说,虽然HTTP使用了TCP来保证数据的可靠传输,但是通信的双方在交换HTTP报文之前不需要提前建立HTTP连接。
HTTP协议是无状态的,也就是说,服务器不会去记忆HTTP的状态,所以不需要额外的资源来记录状态信息,这可以减轻服务器的负担,能够把更多的CPU用来向外提供服务。但是很多请求操作是有关联性的,比如购物下单支付等,这个可以使用Cookie来解决无状态问题。
HTTP协议首先需要和服务器建立TCP连接,这需要用到三报文握手。当建立TCP连接的三报文握手的前两部分完成后,客户就把HTTP请求报文,作为TCP连接的三报文握手中的第三个报文(第三次握手)的数据,发送给服务器。
- HTTP1.0协议中,客户机和服务器每次建立新的TCP连接都要分配缓存和变量,特别是服务器需要同时服务于大量客户的请求,这种非持续连接会使服务器的负担很重。
# HTTP状态码
响应头对浏览器来说很重要,它说明了响应的真正含义。例如200 表示响应成功了,302表示重定向,这说明浏览器需要再发一个新的请求。 2xx 表示成功,3xx 表示重定向,4xx 表示客户端出错,5xx 表示服务器出错。
200:请求成功,浏览器会把响应体内容(通常是html)显示在浏览器中;
404:请求的资源没有找到,说明客户端错误的请求了不存在的资源;
500:请求资源找到了,但服务器内部出现了错误;
302:重定向,当响应码为302 时,表示服务器要求浏览器重新再发一个请求,服务器会发送一个响应头Location,它指定了新请求的URL 地址;
304:(缓存)‘
# 1xx(临时响应)
表示临时响应并需要请求者继续执行操作的状态码。
100(继续) | 请求者应当继续提出请求。服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。 |
---|---|
101(切换协议) | 请求者已要求服务器切换协议,服务器已确认并准备切换。 |
# 2xx (成功)
表示成功处理了请求的状态码。
200(成功) | 服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。如果是对您的 robots.txt 文件显示此状态码,则表示 Googlebot 已成功检索到该文件。 |
---|---|
201(已创建) | 请求成功并且服务器创建了新的资源。 |
202(已接受) | 服务器已接受请求,但尚未处理。 |
203(非授权信息) | 服务器已成功处理了请求,但返回的信息可能来自另一来源。 |
204(无内容) | 服务器成功处理了请求,但没有返回任何内容。响应头没有body数据。 |
205(重置内容) | 服务器成功处理了请求,但没有返回任何内容。与 204 响应不同,此响应要求请求者重置文档视图(例如,清除表单内容以输入新内容)。 |
206(部分内容) | 服务器成功处理了部分 GET 请求。常用于分块下载或者端点续传。 |
# 3xx (重定向)
300(多种选择) | 针对请求,服务器可执行多种操作。服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。 |
---|---|
301(永久移动) | 请求的网页已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。 |
302(临时移动) | 请求的资源还在,但暂时需要用另一个URL来访问。 |
303(查看其他位置) | 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。对于除 HEAD 之外的所有请求,服务器会自动转到其他位置。 |
304(未修改) | 自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。重定向已存在的缓存文件,也称作缓存重定向。 |
305(使用代理) | 请求者只能使用代理访问请求的网页。如果服务器返回此响应,还表示请求者应使用代理。 |
307(临时重定向) | 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来响应以后的请求。此代码与响应 GET 和 HEAD 请求的 <a href=answer.py?answer=>301 代码类似,会自动将请求者转到不同的位置,但您不应使用此代码来告诉 Googlebot 某个页面或网站已经移动,因为 Googlebot 会继续抓取原有位置并编制索引。 |
# 4xx(请求错误)
这些状态码表示请求可能出错,妨碍了服务器的处理。
400(错误请求) | 服务器不理解请求的语法。 |
---|---|
401(未授权) | 请求要求身份验证。对于登录后请求的网页,服务器可能返回此响应。 |
403(禁止) | 服务器拒绝请求。服务器禁止访问资源,并不是客户端的请求出错。 |
404(未找到) | 服务器找不到请求的网页。 |
405(方法禁用) | 禁用请求中指定的方法。 |
406(不接受) | 无法使用请求的内容特性响应请求的网页。 |
407(需要代理授权) | 此状态码与 <a href=answer.py?answer=35128>401(未授权)类似,但指定请求者应当授权使用代理。如果服务器返回此响应,还表示请求者应当使用代理。 |
408(请求超时) | 服务器等候请求时发生超时。 |
409(冲突) | 服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息。服务器在响应与前一个请求相冲突的 PUT 请求时可能会返回此代码,以及两个请求的差异列表。 |
410(已删除) | 如果请求的资源已永久删除,服务器就会返回此响应。该代码与 404(未找到)代码类似,但在资源以前存在而现在不存在的情况下,有时会用来替代 404 代码。如果资源已永久移动,您应使用 301 指定资源的新位置。 |
# 5xx(服务器错误)
这些状态码表示服务器在处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错。
500(服务器内部错误) | 服务器遇到错误,无法完成请求。 |
---|---|
501(尚未实施) | 服务器不具备完成请求的功能。例如,服务器无法识别请求方法时可能会返回此代码。即将开业,敬请期待。 |
502(错误网关) | 服务器作为网关或代理,从上游服务器收到无效响应。 |
503(服务不可用) | 服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。网络服务正忙,请稍后重试。 |
504(网关超时) | 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 |
505(HTTP 版本不受支持) | 服务器不支持请求中所用的 HTTP 协议版本。 |
# GET 和POST 请求的区别?
幂等意味着对同一URL 的多个请求应该返回同样的结果。
安全指的是请求方法不会破坏服务器上的资源。
前者将请求参数放在URL 中,文本格式;后者将请求参数放在请求体(body)中,可以是文本、二进制等格式
前者语义上是从服务器获取资源,安全(无副作用)、幂等、可缓存;后者语义上是向服务器提交资源,不安全(有副作用)、不幂等、不可缓存
前者的URL 是明文传输,会保存在浏览器历史记录中,安全性不足,可能会受到CSRF攻击;后者较为安全(但是如果没有加密的话,都是可以明文获取的)
# HTTP的安全问题
通信使用明文,不加密,导致内容可能被窃听。比如账号信息泄露等。
不验证通信方的身份,因此有可能遭遇伪装,比如访问假的淘宝网站等。
无法证明报文的完整性,可能已经遭遇篡改。
# HTTP与HTTPS的区别
HTTP是超文本传输协议,信息是明文传输,存在安全风险。HTTPS则是解决HTTP不安全的缺陷,在TCP和HTTP之间加入了SSL/TLS安全协议,使得报文能够加密传输。
HTTP连接的建立相对简单,使用TCP三次握手就可以进行HTTP报文的传输。而HTTPS在TCP三次握手之后,还需要进行SSL/TLS握手过程,才能进入加密报文传输。
HTTP的端口号是80,HTTPS的端口号是443。
HTTPS协议需要向CA申请数字证书,来保证服务器的身份是可信的。
# HTTPS使用的SSL/TLS核心技术分析
# 混合加密-保证机密性
# 摘要算法-保证完整性
# 数字证书-防篡改
# HTTPS与SSL/TLS连接
参考文章:https://www.yuque.com/hanchanmingqi-zjjw3/kb/uclmkq (opens new window)
# http各版本的改进
# http1.1
HTTP1.1最大的变化就是引入了长连接,也就是TCP链接默认是不关闭的可以被多个请求复用。对于同一个域名,目前浏览器支持建立6个长链接。
支持管道(pipeline,流水线)网络传输,只要第一个请求发出去了,不必等其回来,就可以发送第二个请求出去,可以减少整体的响应时间。
节约带宽,HTTP1.1支持只发送header头信息不带任何body信息,如果服务器认为客户端有权限请求指定数据那就返回100,没有就返回401,当客户端收到100的时候可以才把要请求的信息发给服务器。并且1.1还支持了请求部分内容,如果当前客户端已经有一部分资源了,只需要向服务器请求另外的部分资源即可,这也是支持文件断点续传的基础。
1.1版本中增加了host处理,在HTTP1.0中认为每台服务器都绑定一个唯一的ip地址,因此在URL中并没有传递主机名,但是随着虚拟机技术的发展,可能在一台物理机器上存在多个虚拟主机,并且他们共享了一个ip地址,http1.1中请求消息和响应消息都支持host头域,如果不存在还会报出错误
# http2.0
多路复用:在一个连接里面并发处理请求,不像http1.1在一个tcp连接中各个请求是串行的。花销很大
在1.0版本后增加了header头信息,2.0版本通过算法对header进行了压缩(如果同时发送多个请求,而且请求头是一样的,那么协议将会消除重复的部分),这样数据体积就更小,在网络上传输就更快。
服务端有了推送功能,将客户端感兴趣的东西推给客户端,当客户端请求这些时,直接去缓存中取就行。
# http3.0
考虑到HTTP2中,多个HTTP请求复用一个TCP连接,下层的TCP协议不知道有多少个HTTP请求。一旦发生了丢包现象,就会触发TCP的重传机制,这样在一个TCP连接里的所有HTTP请求都必须等待这个丢失的包被重传回来。
HTTP3.0最大的变化就是,将HTTP下层的TCP协议改成了UDP协议。
此外,HTTP3.0将QUIC协议与UDP协议结合起来,可以实现类似于TCP的可靠性传输。QUIC有自己的一套机制来保证传输的可靠性,当某个流丢失时,只会阻塞这个流,其他流不会受到影响。
HTTPS要建立一个连接,需要六次交互,而QUIC将交互合并成了三次。
# Cookie和Session
HTTP协议是一种无状态协议,也就是说每次服务器接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录。Session和Cookie的主要目的就是为了弥补HTTP的无状态特性。
对于Session来说,客户端请求服务端,服务端会为这次请求开辟一块内存空间,这个对象就是Session对象,存储结构为ConcurrentHashMap。服务器可以利用Session存储客户端在同一会话期间的一些操作。典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。
Session机制的一个缺点就是,比如服务器存储了Session,在做了负载均衡之后,同一个客户端A的请求会被转发到B进行访问,但是B服务器并没有存储A的Session,会导致Session的失效。在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。
思考一下服务端如何识别特定的客户?这个时候Cookie就登场了。它是服务器发送到Web浏览器的一小块数据,浏览器会进行存储,并在每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。
实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。有人问,如果客户端的浏览器禁用了 Cookie 怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
Cookie其实还可以用在一些方便用户的场景下,设想你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办?这个信息可以写到Cookie里面,访问网站的时候,网站页面的脚本可以读取这个信息,就自动帮你把用户名给填了,能够方便一下用户。这也是Cookie名称的由来,给用户的一点甜头。
所以,总结一下:
Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
# 基于 Token 的身份验证
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:
客户端使用用户名跟密码请求登录
服务端收到请求,去验证用户名与密码
验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据