1.HTTP简介
HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容优先显示。
2.HTTP协议所在的协议层
HTTP协议是基于TCP协议之上的应用层。
3. HTTP请求响应模型
HTTP是由请求和响应组成的,是一个标准的客户端服务器模型。永远都是客户端先发起的请求,服务器再响应请求。
HTTP是一个无状态的面向连接协议,所谓的无状态是指,不会保留之前连接的信息。
4.HTTP工作流程
- 地址解析
从客户端请求路径中解析协议名、主机名、端口、资源路径等信息。
如果是域名,需要通过DNS服务器获取域名主机的IP地址,然后再解析响应的端口和资源对象路径。 - 封装HTTP请求数据包
将上一步解析的数据与本机信息封装成一个HTTP请求数据包。 - 建立TCP连接
通过TCP协议与服务端建立网络连接。 - 客户端发送请求命令
建立TCP连接后,将HTTP数据包发送给服务端,这个包就是HTTP请求,请求行中包括请求方法、资源标识符URI和HTTP版本号。后面跟着各种首部字段,包括请求和响应的各种条件和属性的各类首部。 - 服务器响应
服务器接收到请求后,回复响应报文,响应报文的状态行包括:响应结果的状态码,原因短语和HTTP版本。后面同样首部字段,然后用一个空格行作为间隔,最后报文主体,也就是实际请求的数据。 - 服务器关闭TCP连接
当服务端完成数据响应,它就会关闭这个TCP连接。但是如果请求头的首部字段中的Connection属性值为keep-alive,那么TCP连接还是会保持再连接状态。
URI:统一资源标志符(Uniform Resource Identifier, URI),表示的是web上每一种可用的资源,如 HTML文档、图像、视频片段、程序等都由一个URI进行标识的。
URL:是URI的一个子集。它是Uniform Resource Locator的缩写,译为“统一资源定位 符”。
URI和URL都定义了资源是什么,但URL还定义了该如何访问资源。URL是一种具体的URI,它是URI的一个子集,它不仅唯一标识资源,而且还提供了定位该资源的信息。URI 是一种语义上的抽象概念,可以是绝对的,也可以是相对的,而URL则必须提供足够的信息来定位,是绝对的。
5.HTTP请求格式
HTTP请求由三个部分组成:请求行、首部字段和报文主体。
其中首部字段还可以分为请求首部字段、通用首部字段和实体首部字段。
以下面这个HTTP请求为例
POST /index.html HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://localhost/
Content-Length:25
Content-Type:application/x-www-form-urlencoded
username=aa&password=1234
1)请求行
请求的第一行是分别:方法 URI 协议/版本,请求行以空格分隔。然后用换行结束。格式如下:
POST /index.html HTTP/1.1
- 请求方法必须大写
HTTP1.1的8种请求方式
HTTP的请求行种包含多中请求方式,这些请求方式表明了要以何种方式来处理URI所标识的资源。
方法 | 功能 |
---|---|
GET | 请求获取由 Request-URI 所标识的资源 |
POST | 请求服务器接收在请求中封装的实体,并将其作为由 Request-Line 中的 Request-URI 所标识的资源的一部分 |
HEAD | 请求获取由 Request-URI 所标识的资源的响应消息报头 |
PUT | 请求服务器存储一个资源,并用 Request-URI 作为其标识符 |
DELETE | 请求服务器删除由 Request-URI 所标识的资源 |
TRACE | 请求服务器回送到的请求信息,主要用于测试或诊断 |
CONNECT | 要求利用隧道协议连接代理 |
OPTIONS | 询问支持的方法,或者查询与资源相关的选项和需求 |
-
GET
GET 方法用于获取由 Request-URI 所标识的资源的信息,GET方法是默认的HTTP请求方法,例如当我们通过在浏览器的地址栏中直接输入网址的方式去访问网页的时候,浏览器采用的就是 GET 方法向服务器获取资源。
我们可以使用GET方法来提交表单数据,用GET方法提交的表单数据只经过了简单的编码,同时它将作为URL的一部分向服务器发送,因此,如果使用GET方法来提交表单数据就存在着安全隐患上。同时数据的长度十分有限,因为浏览器对URL的长度会有限制。
Http://localhost/login.php?username=aa&password=1234 -
POST
POST方法是GET的一个代替方法,主要用于向服务端提交数据,特别是大量的数据。 在请求头信息结束之后的两个回车换行之后(实际是空一行),就是表单提交的数据。
POSt方法不同于GET方法提交表单,它是把数据放到了报文主体中,而不是编入URL中,这样就克服了GET方法的不安全性和数据量小的问题。通常提交表单需要采用POST方法。
从编程的角度上来说,GET方法提交的数据可以再环境变量中获取,而POST的数据可以在标准输出流中获取。
- HEAD
HEAD 方法与 GET 方法很相似,它们的区别在于 HEAD 方法只是请求消息报头,而不是完整的内容。对于 HEAD 请求的回应部分来说,它的 HTTP 头部中包含的信息与通过 GET 请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到 Request-URI 所标识的资源的信息。这个方法通常被用于测试超链接的有效性,是否可以访问,以及最近是否更新。
GET和POST比较
- 客户端的角度,GET方法通过URL提交数据,而POST方法的数据放在了HTTP请求的报文主体中。
- GET提交的数据大小有限制而且有安全性问题,而POST没有。
- 服务端代码编写时,获取数据的方式也不一样。
- POST请求在很多浏览器上可能会发送两个包,先发送头,再发送主体。
2)首部字段
HTTP首部字段是为了给浏览器和服务器提供报文主体大小、连接管理、日期、主机端口、请求数据范围、所使用的语言、认证信息等内容。
首部字段由字段名和字段值构成,中间用" : "分开。
首部字段还分为通用首部、请求首部、响应首部和实体首部。
常用的有:
- user-agent:向访问网站提供你所使用的浏览器类型、操作系统及版本、CPU 类型、浏览器渲染引擎、浏览器语言、浏览器插件等信息的标识。
3)报文主体
包含请求中需要被发送的数据,不是所有的请求都具有报文主体,GET就没有,POST就有。
6.HTTP响应格式
在接收和解释请求消息后,服务器会返回一个 HTTP 响应消息。与 HTTP 请求类似,HTTP 响应也是由三个部分组成,分别是:状态行、首部字段和报文主体。如:
HTTP/1.1 200 OK
Date: Sun, 17 Mar 2013 08:12:54 GMT
Server: Apache/2.2.8 (Win32) PHP/5.2.5
X-Powered-By: PHP/5.2.5
Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 4393
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8
<html>
<head>
<title>HTTP响应示例<title>
</head>
<body>
Hello HTTP!
</body>
</html>
1)状态行
状态行由协议版本、状态代码,及相应的状态描述组成,各元素之间以空格分隔,结尾时回车换行符,举例格式如下:
HTTP/1.1 200 OK
状态代码由 3 位数字组成, 表示请求是否被理解或被满足,状态描述给出了关于状态码的简短的文字描述。状态码的第一个数字定义了响应类别,后面两位数字没有具体分类。
- 常见的状态码
状态码 | 功能 |
---|---|
100 Continue | 继续发送。 |
101 Swithing protocol | 要求客户端切换协议。 |
200 OK | 客户端请求成功。 |
204 No Content | 请求成功但是没有数据。 |
206 Partail Content | 请求部分的数据。 |
301 Moved Permanently | 永久重定向。 |
302 Found | 临时性重定向 |
303 See Other | 临时性重定向,即从原url重定向到新的url。 与302的功能相同,区别在于要求客户端以GET方式请求。 |
400 Bad Request | 客户端请求有语法错误,不能被服务器所理解。 |
401 Unauthorized | 请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 。 |
403 Forbidden | 服务器收到请求,但是拒绝提供服务,一般是服务器路径没有权限或者是其他权限相关问题。 |
404 Not Found | 请求资源不存在,eg:输入了错误的URL。 |
500 Internal Server Error | 服务器发生不可预期的错误:一般来说,这个问题都会在服务器端的源代码出现错误时出现,比如出现死循环。 |
502 Bad Gateway | 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。 |
503 Server Unavailable | 服务器当前不能处理客户端的请求,一段时间后可能恢复正常,比如java容器部署war的时候,就出现503。或者是nginx处理的文件没有权限。 |
504 Gateway Time-out | 作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTP、FTP、LDAP)或者辅助服务器(例如DNS)收到响应,比如nginx和php-fpm, php设置sleep(200),就会收到504 Gateway Time-out。注意:某些代理服务器在DNS查询超时时会返回400或者500错误 |
2)首部字段
响应报文的首部字段和请求报文的首部字段都是具有通用首部字段,然后响应报文由自己的响应首部。这些字段功能大多围绕响应报文的状态码,做一个补充。
例如,状态码是重定向,那么首部字段中就会包含重定向信息,新的URL。
3)报文主体
这里就是服务端返回的资源内容,报文首部和主体之间也通过一个空行隔开。
7.HTTP1.0和HTTP1.1区别
1)增加和废弃的请求方法
增加的:
- OPTIONS
- CONNECT
废弃的:
- LINK
- UNLINK
详细作用可以看之前的部分。
2)增加的状态码
100 Continue
101 Switching Protocols
203 Non-Authoritative Information
205 Reset Content
206 Partial Content
302 Found (在HTTP1.0中有个 302 Moved Temporarily)
303 See Other
305 Use Proxy
307 Temporary Redirect
405 Method Not Allowed
406 Not Acceptable
407 Proxy Authentication Required
408 Request Timeout
409 Conflict
410 Gone
411 Length Required
412 Precondition Failed
413 Request Entity Too Large
414 Request-URI Too Long
415 Unsupported Media Type
416 Requested Range Not Satisfiable
417 Expectation Failed
504 Gateway Timeout
505 HTTP Version Not Supported
3)连接管理
HTTP1.0中,每对请求/响应都使用一个新的连接。
HTTP 1.1则支持持久连接Persistent Connection, 并且默认使用persistent connection. 在同一个tcp的连接中可以传送多个HTTP请求和响应. 多个请求和响应可以重叠,多个请求和响应可以同时进行. 更加多的请求头和响应头(比如HTTP1.0没有host的字段)
HTTP 1.1的持续连接,也需要增加新的请求头来帮助实现,例如,Connection请求头的值为Keep-Alive时,客户端通知服务器返回本次请求结果后保持连接;Connection请求头的值为close时,客户端通知服务器返回本次请求结果后关闭连接。HTTP 1.1还提供了与身份认证、状态管理和Cache缓存等机制相关的请求头和响应头。
- 持久连接的好处:减少TCP连接与断开的开销。
4)HOST域
在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。
HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。此外,服务器应该接受以绝对路径标记的资源请求。
1.0的时候认为既然已经访问到主机了,就直接用只带资源路径的URI就能访问到相应的资源了,但是,后来一个主机上又虚拟化出了很多主机,找到一个IP上的主机是不能获得准确的资源位置的,所以,1.1加入了HOST字段,用来标识一个IP上的不同主机。
5)date/timestamp (日期时间戳)
规定的时间表示格式不同了。
6)100 Status(节约带宽)
HTTP1.1加入了100状态码,用于响应客户端,是否可以接收客户端发送的数据。
如果贸然向服务端发送数据,服务端还不要的时候,就会浪费网络带宽,所以,可以先发一个不带主体主句的报文头部,如果服务端要这个数据,就回复100,不要就回复401。
如果客户端只是需要对象的某一个部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
7)缓存
在HTTP/1.0中,使用Expire字段来判断资源的fresh或stale,并使用条件请求(conditional request)来判断资源是否仍有效。例如,cache服务器通过If-Modified-Since头域向服务器验证资源的Last-Modefied头域是否有更新,源服务器可能返回304(Not Modified),则表明该对象仍有效;也可能返回200(OK)替换请求的Cache对象。
此外,HTTP/1.0中还定义了Pragma:no-cache头域,客户端使用该头域说明请求资源不能从cache中获取,而必须回源获取。
HTTP/1.1在1.0的基础上加入了一些cache的新特性,当缓存对象的Age超过Expire时变为stale对象,cache不需要直接抛弃stale对象,而是与源服务器进行重新激活(revalidation)。还加入了其他很多缓存相关的特性。
8.HTTP2.0的新特性
- 新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
- 多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
- header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
- 服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。
9.HTTP的缺点
- 通信使用明文,内容可能会被窃听。
- 不验证通信方的身份,可能遭遇伪装。
- 无法证明报文的正确性,可能被篡改。
10.HTTPS协议
HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层加密处理和认证以及完整性保护后的模块。克服了上面介绍的三个缺陷。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。
HTTP和HTTPS的区别
- HTTPS就是将HTTP与TCP的接口部分用SSL和TLS协议代替了而已。HTTP直接和TCP通信,而HTTPS中,是先和SSL通信,然后SSL再和TCP通信。SSL是独立于HTTP的,其他的应用也能使用SSL,这个当今世界应用最为广泛的网络安全计数。
- HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。
- HTTP和HTTPS使用的是完全不同的连接方式。
- 用的端口也不一样,前者是80,后者是443。
- HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。
HTTPS 连接
在建立TCP连接之后:
- 客户端发给服务器一个HELLO包,里面有其支持的加密协议列表。服务器收到后发送也给客户端发送一个HELLO数据包,数据包内包括服务器挑选的加密算法,还包含自己的数字证书信息。
- 客户端数字证书信息之后就需要去向 CA 校验证书,校验成功后也知道了对方的公钥,就该通知服务器,我们以后对称加密的密码是多少,当然,这个密码是要用公钥加密的。
- 在这条消息发送之前,客户端会先发送一条消息,告诉服务器,我下一个消息将使用你刚刚挑选的加密协议进行加密了,下一个消息是加密后的哦,不要搞错。之后将对称加密的密文发给服务器。
- 服务器接收到之后,会根据对称密钥生成一系列复杂的加密算法,在传输给客户端。
- 客户端收到后会给服务器发送一个 Finished Message ,服务器收到消息后也回一个 Finished Message。这时,我们终于完成了加密的准备工作,一切加密方式和密钥都商量好了,终于可以传输数据了。至此,TSL 建立连接的过程结束。
ps:和下面的加密流程有所重复。
HTTPS 采用的混合加密机制
HTTPS采用共享密钥和公开密钥两种方式混合加密的机制。
- 共享密钥:就是双方用同一把钥匙对数据进行加密和解密。
- 公开密钥:发送方用公钥进行加密,然后接收方用私钥进行解密。公钥是谁都能获取的,私钥只有自己有,不会发给别人,这样就安全多了。
共享密钥的效率高,但是安全性低。公开密钥处理速度慢,安全性高。
如果确保交换的密钥是安全的,就会用共享密钥加密。
- 如何确保公开密钥的公钥是正确的呢?
需要利用第三方数字认证机构发放的证书授权确认。
工作流程
具体是如何进行加密,解密,验证的。
- 客户端发起HTTPS请求。
- 服务端的配置。
采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面。这套证书其实就是一对公钥和私钥。 - 传送证书。
这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。 - 客户端解析证书
这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随即值。然后用证书对该随机值进行加密。 - 客户端传送随机值。
这部分传送的是用证书加密的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。 - 服务端解密随机值。
服务端用证书私钥解密后,得到了客户端传过来的随机值(共享的私钥),然后把内容通过该值进行对称加密。所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够好,私钥够复杂,数据就够安全。 - 服务端传输加密后的信息。
- 客户端解密。
我的一些理解
这个流程中出现了两个私钥,一个是配对证书的中的私钥,这把私钥是只有服务端才有的,而且只是在开头的时候才会使用,用来获取客户端自己产生的随机共享私钥的。客户端在获取证书之后,就用证书中的公钥加密自己产生的新私钥,然后把这个新私钥给客户端,之后的通信就不需要传输钥匙了,直接通过这把新私钥进行加密和解密。
所以,HTTPS所谓的混合加密机制在这里就很明显体现出来了,在开始利用公私钥的方式,确保共享密钥的安全,然后再用共享密钥对信息进行加密和解密,这样,既保证了共享密钥的安全,有提高了后面数据加密和解密的处理速度,很完美。
HTTP缓存
浏览器缓存分为强缓存和协商缓存,浏览器加载一个页面的简单流程如下:
- 浏览器先根据这个资源的http头信息来判断是否命中强缓存。如果命中则直接加在缓存中的资源,并不会将请求发送到服务器。
- 如果未命中强缓存,则浏览器会将资源加载请求发送到服务器。服务器来判断浏览器本地缓存是否失效。若可以使用,则服务器并不会返回资源信息,浏览器继续从缓存加载资源。
- 如果未命中协商缓存,则服务器会将完整的资源返回给浏览器,浏览器加载新资源,并更新缓存。