一、Http报文
http报文可以分为请求报文和响应报文,格式大同小异。主要分为三个部分:
(1)起始行
(2) 首部
(3) 主体
请求报文格式:
响应报文格式:
从请求报文格式和响应报文格式可以看出,两者主要在起始行上有差异。这里稍微解释一下各个标签:
二、method
GET和POST两个方法之间在传输形式上有一些区别,通过Get方法发起请求时,会将请求参数拼接在request-url尾部,格式是url?param1=xxx¶m2=xxx&[…]。
我们需要知道,这样传输参数会使得参数都暴露在地址栏中。并且由于url是ASCII编码的,所以参数中如果有Unicode编码的字符,例如汉字,都会编码之后传输。另外值得注意的是,虽然http协议并没有对url长度做限制,但是一些浏览器和服务器可能会有限制,所以通过GET方法发起的请求参数不能够太长。而通过POST方法发起的请求是将参数放在请求体中的,所以不会有GET参数的这些问题。
另外一点差别就是方法本身的语义上的。GET方法通常是指从服务器获取某个URL资源,其行为可以看作是一个读操作,对同一个URL进行多次GET并不会对服务器产生什么影响。而POST方法通常是对某个URL进行添加、修改,例如一个表单提交,通常会往服务器插入一条记录。多次POST请求可能导致服务器的数据库中添加了多条记录。所以从语义上来讲,两者也是不能混为一谈的。
概括:
1、GET请求会将请求参数拼接在request-url尾部,POST放在请求体中;
2、GET请求需要对参数中的中文编码之后传输;
3、有些浏览器和服务器可能会对url长度有限制,如果请求参数过长,那么就得使用POST请求方法;
4、GET方法通常是指从服务器获取某个URL资源,可以看做读操作;而POST方法通常是对某个URL进行添加、修改,通常会往服务器插入一条记录。
三、状态码
常见的状态码主要有
200 OK 请求成功,实体包含请求的资源。
301 Moved Permanent 请求的URL被移除了,通常会在Location首部中包含新的URL用于重定向。
304 Not Modified 条件请求进行再验证,资源未改变。
404 Not Found 资源不存在
206 Partial Content 成功执行一个部分请求。这个在用于断点续传时会涉及到。
四、header
在请求报文和响应报文中都可以携带一些信息,通过与其他部分配合,能够实现各种强大的功能。这些信息位于起始行之下与请求实体之间,以键值对的形式,称之为首部。每条首部以回车换行符结尾,最后一个首部额外多一个换行,与实体分隔开。
这里我们重点关注一下
Date
Cache-Control
Last-Modified
Etag
Expires
If-Modified-Since
If-None-Match
If-Unmodified-Since
If-Range
If-Match
Http的首部还有很多,但限于篇幅我们不一一讨论。这些首部都是Http缓存会涉及到的,在下文中我们会来说说各自的作用。
五、实体
请求发送的资源,或是响应返回的资源。
六、Http缓存
缓存:将http请求服务器获取到的资源副本存到本地,下次对该url资源请求的时候,快速的从本地存储设备中获取到该url资源。
优点:既可以节约不必要的网络带宽,又能迅速对http请求做出响应。
先摆出几个概念: 1、新鲜度检测 2、再验证 3、再验证命中
时间差异:有些url所对应的资源并不是一成不变的,服务器中该url的资源可能在一定时间之后会被修改。这时本地缓存中的资源将与服务器一侧的资源有差异。
新鲜度检测:既然在一定时间之后可能资源会改变,那么在某个时间之前我们可以认为这个资源没有改变,从而放心大胆的使用缓存资源,当请求时间超过来该时间,我们认为这个缓存资源可能不再与服务器端一致了。所以当我们发起一个请求时,我们需要先对缓存的资源进行判断,看看究竟我们是否可以直接使用该缓存资源,这个就叫做新鲜度检测。即每个资源就像一个食品一样,拥有一个过期时间,我们吃之前需要先看看有没有过期。
再验证:如果发现该缓存资源已经超过了一定的时间,我们再次发起请求时不会直接将缓存资源返回,而是先去服务器查看该资源是否已经改变,这个就叫做再验证。
再验证命中:如果服务器发现对应的url资源并没有发生变化,则会返回304 Not Modified,并且不再返回对应的实体。这称之为再验证命中。相反如果再验证未命中,则返回200 OK,并将改变后的url资源返回,此时缓存可以更新以待之后请求。
1、新鲜度检测 我们需要通过检测资源是否超过一定的时间,来判断缓存资源是否新鲜可用。那么这个一定的时间怎么决定呢?其实是由服务器通过在响应报文中增加Cache-Control:max-age,或是Expire这两个首部来实现的。值得注意的是Cache-Control是http1.1的协议规范,通常是接相对的时间,即多少秒以后,需要结合last-modified这个首部计算出绝对时间。而Expire是http1.0的规范,后面接一个绝对时间。 2、再验证 如果通过新鲜度检测发现需要请求服务器进行再验证,那么我们至少需要告诉服务器,我们已经缓存了一个什么样的资源了,然后服务器来判断这个缓存资源到底是不是与当前的资源一致。逻辑是这样没错。那怎么告诉服务器我当前已经有一个备用的缓存资源了呢?我们可以采用一种称之为条件请求的方式实现再验证。 3、Http定义了5个首部用于条件请求: If-Modified-Since If-None-Match If-Unmodified-Since If-Range If-Match
If-Modified-Since 可以结合Last-Modified这个服务器返回的响应首部使用,当我们发起条件请求时,将Last-Modified首部的值作为If-Modified-Since首部的值传递到服务器,意思是查询服务器的资源自从我们上一次缓存之后是否有修改。
If-None-Match 需要结合另一个Etag的服务器返回的响应首部使用。Etag首部实际上可以认为是服务器对文档资源定义的一个版本号。有时候一个文档被修改了,可能所做的修改极为微小,并不需要所有的缓存都重新下载数据。或者说某一个文档的修改周期极为频繁,以至于以秒为时间粒度的判断已经无法满足需求。这个时候可能就需要Etag这个首部来表明这个文档的版号了。发起条件请求时可将缓存时保存下来的Etag的值作为If-None-Match首部的值发送至服务器,如果服务器的资源的Etag与当前条件请求的Etag一致,表明这次再验证命中。
其他三个与断点续传涉及到的相关知识有关,本文暂时不讨论。待我之后写一篇文章来讲讲断点续传。
七、OkHttp的缓存
OkHttp缓存流程总结:
1、从接收到的请求中,解析出Url和各个首部。 2、查询本地是否有缓存副本可以使用。 3、如果有缓存,则进行新鲜度检测,如果缓存足够新鲜,则使用缓存作为响应返回,如果不够新鲜了,则构造条件请求,发往服务器再验证。如果没有缓存,就直接将请求发往服务器。 4、把从服务器返回的响应,更新或是新增到缓存中。
八、OAuth
OAuth是一个用于授权第三方获取相应资源的协议。与以往的授权方式不同的是,OAuth的授权能避免用户暴露自己的用户密码给第三方,从而更加的安全。OAuth协议通过设置一个授权层,以区分用户和第三方应用。用户本身可以通过用户密码登陆服务提供商,获取到账户所有的资源。而第三方应用只能通过向用户请求授权,获取到一个Access Token,用以登陆授权层,从而在指定时间内获取到用户授权访问的部分资源。
从上图可以看出,一个OAuth授权的流程主要可以分为6步:
1、客户端向用户申请授权。
2、用户同意授权。
3、客户端通过获取的授权,向认证服务器申请Access Token。
4、认证服务器通过授权认证后,下发Access Token。
5、客户端通过获取的到Access Token向资源服务器发起请求。
6、资源服务器核对Access Token后下发请求资源。
九、Https
简单的说 Http + 加密 + 认证 + 完整性保护 = Https
传统的Http协议是一种应用层的传输协议,Http直接与TCP协议通信。其本身存在一些缺点:
1、Http协议使用明文传输,容易遭到窃听。
2、Http对于通信双方都没有进行身份验证,通信的双方无法确认对方是否是伪装的客户端或者服务端。
3、Http对于传输内容的完整性没有确认的办法,往往容易在传输过程中被劫持篡改。
因此,在一些需要保证安全性的场景下,比如涉及到银行账户的请求时,Http无法抵御这些攻击。
Https则可以通过增加的SSL\TLS,支持对于通信内容的加密,以及对通信双方的身份进行验证。
十、Https的加密
近代密码学中加密的方式主要有两类:
1、对称秘钥加密
2、非对称秘钥加密
对称秘钥加密是指加密与解密过程使用同一把秘钥。这种方式的优点是处理速度快,但是如何安全的从一方将秘钥传递到通信的另一方是一个问题。
非对称秘钥加密是指加密与解密使用两把不同的秘钥。这两把秘钥,一把叫公开秘钥,可以随意对外公开。一把叫私有秘钥,只用于本身持有。得到公开秘钥的客户端可以使用公开秘钥对传输内容进行加密,而只有私有秘钥持有者本身可以对公开秘钥加密的内容进行解密。这种方式克服了秘钥交换的问题,但是相对于对称秘钥加密的方式,处理速度较慢。
SSL\TLS的加密方式则是结合了两种加密方式的优点。首先采用非对称秘钥加密,将一个对称秘钥使用公开秘钥加密后传输到对方。对方使用私有秘钥解密,得到传输的对称秘钥。之后双方再使用对称秘钥进行通信。这样即解决了对称秘钥加密的秘钥传输问题,又利用了对称秘钥的高效率来进行通信内容的加密与解密。
对称加密和非对称加密的区别:1、对称加密(加密和解密用同一个秘钥)处理速度快,非对称处理速度慢;2、对称加密秘钥传输过程中容易被篡改,安全系数低;非对称加密分公钥和私钥,安全系数相对较高。
十一、Https的认证
SSL\TLS采用的混合加密的方式还是存在一个问题,即怎么样确保用于加密的公开秘钥确实是所期望的服务器所分发的呢?也许在收到公开秘钥时,这个公开秘钥已经被别人篡改了。因此,我们还需要对这个秘钥进行认证的能力,以确保我们通信的对方是我们所期望的对象。
目前的做法是使用由数字证书认证机构颁发的公开秘钥证书。服务器的运营人员可以向认证机构提出公开秘钥申请。认证机构在审核之后,会将公开秘钥与共钥证书绑定。服务器就可以将这个共钥证书下发给客户端,客户端在收到证书后,使用认证机构的公开秘钥进行验证。一旦验证成功,即可知道这个秘钥是可以信任的秘钥。
总结
Https的通信流程:
1、Client发起请求
2、Server端响应请求,并在之后将证书发送至Client
3、Client使用认证机构的共钥认证证书,并从证书中取出Server端共钥。
4、Client使用共钥加密一个随机秘钥,并传到Server
5、Server使用私钥解密出随机秘钥
6、通信双方使用随机秘钥最为对称秘钥进行加密解密。