http是基于TCP/IP关于数据在万维网中如何通信的应用层协议。
1)基于请求-响应的模式(请求必定由客户端发出,服务器端回复响应)
2)无连接(每次连接只处理一个请求)
3)无状态保存(http本身不对请求-响应的信息做保存,即不做持久化处理)(结合cookie/session,就可以保存和管理状态)
4)简单快速、灵活
5)通信使用明文、请求和响应不会对通信方进行确认、无法保护数据的完整性
p.s. cookie和session都是用来记录客户端状态的机制。不同的是cookie是保存在客户端,而session是保存在服务端。两者最大的区别在于生存周期,一个是IE启动到IE关闭.(浏览器页面一关 ,session就消失了),一个是预先设置的生存周期,或永久的保存于本地的文件。(cookie)
- cookie 是浏览器提供的一种缓存机制,它可以用于维持客户端与服务端之间的会话
- session 指的是维持客户端与服务端会话的一种机制,它可以通过 cookie 实现,也可以通过别的手段实现。
- 如果用 cookie 实现会话,那么会话会保存在客户端浏览器中
- 而 session 机制提供的会话是保存在服务端的
session使用cookie实现的过程:
- 首先用户在客户端浏览器发起登陆请求
- 登陆成功后,服务端会把用户信息保存在服务端,并返回一个唯一的 session 标识给客户端浏览器。
- 客户端浏览器会把这个唯一的 session 标识保存在起来
- 以后再次访问 web 应用时,客户端浏览器会把这个唯一的 session 标识带上,这样服务端就能根据这个唯一标识找到用户信息
一次http的请求全过程:
一、解析URL:浏览器首先会对输入的URL进行检查,如果不合法,会把输入的文字传给默认的搜索引擎--如google、baidu;通过了URL的验证,那么可以解析得到协议(http以及https)、域名、资源等信息;
二、DNS查询:浏览器会先检查域名信息是否在缓存中;再检查域名是否在本地Hosts文件中;如果还不在,那么浏览器就会向DNS服务器发送一个查询的请求,获得目标服务器的ip地址;
三、TCP封包及传输:浏览器获得了目标服务器的ip、端口,浏览器会调用库函数socket,生成一个TCP流套接字,也就是TCP封包;TCP封包完成之后,就可以传输数据了,浏览器和服务器通过TCP三次握手建立连接,后面就可以请求服务器资源了。
四、服务器接受请求并响应:http有很多请求方法,比如:GET/POST/PUT/DELETE等等,我们浏览器输入URL这种,是GET方法;服务器接受GET请求,服务器根据请求信息,获得相应的资源内容。
五、释放TCP连接:connection字段若为keep-alive模式,则保持连接,可以继续接受请求;若为close模式,则服务端主动释放断开连接,客户端被动关闭连接。
六、浏览器解析并渲染:浏览器从服务器拿到了想要的资源,如html页面,首先对html文档进行解析,生成DOM节点树,然后加载页面的外部资源,如css、js、img等;最后遍历DOM树,并计算每个节点的样式,最终完成渲染,变成我们的页面;
http请求报文:
1.请求行:请求方法(get/post)、url、版本号(http/1.1)
2.请求头部:首部字段:value (host:hackr.jp connection:keep-alive content-type:application/x-www-form-urlencoded content-length:16)
1和2组成了报文首部(报文头)
3.实体主体:存储请求的资源信息(name=ueno&age=37)
http响应报文:
1.状态行版本号(http/1.1)、状态码(200)、状态码的原因短语(OK)
2.响应首部
3.实体主体:存放表单数据(如果太大,会把数据分割为多块,分块传送,浏览器逐步显示页面)
http头部字段:
通用头部:
Date:报文的发送时间
Connection:与连接的控制有关。
Transfer_encoding:WEB 服务器表明自己对本响应消息体(不是消息体里面的对象)作了怎样的编码,比如是否分块(chunked)
cache_control:选用的缓存机制 e.g no_cache、public、private
请求头部:
Host:目标服务器的地址。域名或ip+端口号
User_agent:客户端发起请求所使用的应用程序名
Referer:表明客户端是从那个页面发起请求的
Accept:可接受的消息类型
Accept_charset、Accept_encode、Accept_language
if_Match:如果请求的资源etag未发生改变,就进行请求操作
if_Nonematch
if_modified_since:如果在规定时间后,资源发生了改变,就进行请求操作
if_unmodified_since post的时候用
响应头部:
Server:表明服务端使用的程序和版本
Accept_Ranges:表明服务端是否接受请求部分对象。bytes or None
Location:将客户端重定向到的URI
实体头部:
Allow:资源可支持的http方法(get、post。。。)
content_type:实体主体的类型
content_encoding content_language
content_length:实体主体的字节数
content_range:实体主体的位置范围, 一般用于发出部分请求时使用
Etag:一个URI的标志值,比如一个html文件,如果被修改了,其Etag也会别修改,所以,ETag的作用跟Last-Modified的作用差不多,主要供WEB服务器判断一个对象是否改变了。比如前一次请求某个html文件时,获得了其 ETag,当这次又请求这个文件时,浏览器就会把先前获得ETag值发送给WEB服务器,然后WEB服务器会把这个ETag跟该文件的当前ETag进行对比,然后就知道这个文件有没有改变了。
Expires: WEB服务器表明该实体将在什么时候过期,对于过期了的对象,只有在跟WEB服务器验证了其有效性后,才能用来响应客户请求。是 HTTP/1.0 的头部。例如:Expires:Sat, 23 May 2009 10:02:12 GMT. http1.1做了修改,将时间改为寿命,避免客户端与服务器的时间不同步问题。
Last-Modified:WEB服务器认为对象的最后修改时间,比如文件的最后修改时间,动态页面的最后产生时间等等。例如:Last-Modified:Tue, 06 May 2008 02:42:43 GMT
响应状态码:
1XX : 通知信息,如请求收到了,或者正在处理。
2XX : 表示成功,请求正常处理完毕。e.g.200 请求成功
3XX :重定向状态,需要附加操作以完成请求。
4XX : 客户端错误,请求无法正常处理,如请求的资源不存在。e.g.404找不到资源
5XX : 服务器内部错误,处理请求时出错。
post V.S. get
1.post 比 get 更加安全,get请求的参数直接暴露在url上,而url是对所有人可见的,不能用来传递敏感信息,而post的参数是放在实体主体中。
2.post 比 get 传输的数据量更大且可以使用更多数据类型。因为get受限于浏览器地址栏的字符数量限制,且只能使用 ASCII码,而post则不受限制。
3.post 比 get 慢。GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据),而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据),相当于三次握手2个RTT和一个发送数据(实体主体)的RTT,一共三个RTT, 而get无实体主体,数据都在url中所以只需三次握手2个RTT, get/post = 2/3。
4.GET请求参数会被完整保留在浏览器历史记录或收藏为书签或缓存,而POST中的参数不会。
在chrome浏览器中,可通过以下操作查看请求头header:按F12进入开发者模式->按F5刷新页面->选择network->点击新出现的内容的任意一行,会出点header,即可点击查看。值得关注的一点是,请求头里面有一个user-agent字段,相当于告诉服务端,我是用什么发送的请求,通过判断该字段可以作为反扒机制的一种。
__________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
https基于http协议,通过ssl或tls提供
加密处理数据(采用混合加密技术,中间者无法直接查看铭文内容)、
验证对方身份(通过证书认证客户端访问的是自己的服务器)
以及数据完整性保护(防止传输的内容被中间人冒充或篡改)。
SSL建立连接:
1、客户端向服务端发送请求url,然后连接到服务端的443端口,发送的信息主要是随机值1和客户端支持的加密算法。
2、服务端接收到信息之后给予客户端响应握手信息,包括随机值2和匹配好的协商加密算法(该加密算法一定是客户端发送给服务端加密算法的子集)。
3、随即服务端给客户端发送第二个响应报文是数字证书。服务端必须要有一套数字证书,可以自己制作,也可以向组织(CA)申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面,这套证书其实就是一对公钥和私钥。传送证书,就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间、服务端的公钥,第三方证书认证机构(CA)的签名,服务端的域名信息等内容。
4、客户端解析证书,这部分工作是由客户端的TLS(传输层的安全协议)来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随即值(预主秘钥)。
5、客户端认证证书通过之后,接下来是通过随机值1、随机值2和预主秘钥组装会话秘钥。然后通过证书的公钥加密会话秘钥。
6、传送加密信息,这部分传送的是用证书加密后的会话秘钥,目的就是让服务端使用秘钥解密得到随机值1、随机值2和预主秘钥。
7、服务端解密得到随机值1、随机值2和预主秘钥,然后组装会话秘钥,跟客户端会话秘钥相同。
8、客户端通过会话秘钥加密一条消息发送给服务端,主要验证服务端是否正常接受客户端加密的消息。(服务端接收消息时,先用私钥解密会话密钥《只解密一次,所以省时》,使用会话密钥解密消息体)
9、同样服务端也会通过会话秘钥加密一条消息回传给客户端,如果客户端能够正常接受的话表明SSL连接建立完成了。
SSL,TSL中的混合密码加密--防窃听
- 对称密码加密(DES,3DES,AES等)无法解决密钥配送问题
- 公钥密码加密(公钥加密,私钥解密) 解决了密钥配送问题,但是效率低
- 所以采用 混合密码加密
信息防篡改
- 但是使用过上述加解密方法后,依然会存在信息被篡改的风险
- sender 发送的内容可能会被篡改,或者有人伪装发送消息
- 问题来了,如何确定消息的真实性?防止被篡改,伪装,否认?
- 解决方法 : 数字签名
- sender 使用 自己的私钥 加密消息(签名)
- receiver 使用 sender的公钥 解密消息
- 可以看出来,数字签名 ,其实就是将消息加密反过来使用
- 消息发送过程就变成这样:
- sender 将 加密后的消息发送给receiver
- 并且,用自己的私钥加密 消息体的散列值
- 将加密后的消息,以及数字签名一块发送给receiver
- reveiver 解密出消息后,对消息进行单向散列函数计算出散列值,并解密出数字签名中的散列值,如果一致,说明不是被篡改。 否则消息被篡改。
- 数字签名解决的问题
- 确认消息的完整性
- 识别消息是否被篡改
- 防止消息发送者抵赖
防伪装
- 数字签名无法解决的问题?
- 要使用 数字签名, 前提得保证 用于验证签名的公钥,必须是真正的发送者的。
- 如果遇到了中间人攻击(Man-In-MiddleAttack)(MITM)
- 中间人伪装再 sender 和 receiver之间, 发送伪造的公钥
- 那么,数字签名,就是去了q签名的效果
- 所以要保证数字签名有效, 首先得验证公钥的合法性
- 如何保证公钥的合法性呢?
- 答案是: 证书
- 证书
- 也叫公钥证书, (Public-key Certificate,PKC)
- 其中包含姓名,邮箱等个人信息,以及此人的公钥
- 并由 认证机构 (Certificate Authoriry, CA机构)施加数字签名
- CA就是能证明公钥却属此人,且能够生成数字签名的组织
- 有国际性组织,政府设立的组织
- 证书如何使用?
- receiver 生成 密钥对
- receiver 在认证机构 注册自己的公钥
- 认证机构用自己的私钥对receiver的公钥进行数字签名
- sender得到带有数字签名的 receiver 公钥(也就是证书)
- receiver使用认证机构的公钥验证签名,验证公钥的合法性
- sender 开始用 receiver 的公钥加密消息并开始通信
- 也叫公钥证书, (Public-key Certificate,PKC)
综合以上, https 可以做到了 防窃听,防止信息被篡改, 防伪装, 确保了通信过程的安全。
为什么服务端要发送证书给客户端
互联网有太多的服务需要使用证书来验证身份,以至于客户端(操作系统或浏览器等)无法内置所有证书,需要通过服务端将证书发送给客户端
http协议加密范围有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面起不到什么作用,且ssl整数的信用链体系并不安全。
考虑到SLL整数需购买申请且等级越高收费越高、https占用占用服务端资源高很多、握手阶段费时影响响应速度等问题,一般网站(e.g12306)采用分而治之的手段,即主页采用http协议,涉及用户信息则使用https协议。
HTTP1.0和HTTP1.1的一些区别
HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较为简单的网页上和网络请求上,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使用最为广泛的HTTP协议。 主要区别主要体现在:
1)缓存处理
在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,
HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
2)带宽优化及网络连接的使用
HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能;
HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
3)错误通知的管理
在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
4)Host头处理
在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。
HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
5)长连接
HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
HTTP2.0和HTTP1.X相比的新特性
1)新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
2)多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
3)header压缩,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
4)服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。
如果服务端收到客户端请求,能够‘预测’主请求的依赖资源,在响应主请求的同时,主动并发推送依赖资源至客户端。客户端解析主请求响应后,可以‘无限时’从本地缓存获取依赖资源,减少访问延时,提高访问体验,也加大了链路的并发能力。例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。
HTTPS和HTTP的区别主要如下:
- https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
- http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
- http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
- http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
HTTP 切换到 HTTPS
如果需要将网站从http切换到https到底该如何实现呢?
这里需要将页面中所有的链接,例如js,css,图片等等链接都由http改为https。例如:http://www.baidu.com改为https://www.baidu.com
BTW,这里虽然将http切换为了https,还是建议保留http。所以我们在切换的时候可以做http和https的兼容,具体实现方式是,去掉页面链接中的http头部,这样可以自动匹配http头和https头。例如:将http://www.baidu.com改为//www.baidu.com。然后当用户从http的入口进入访问页面时,页面就是http,如果用户是从https的入口进入访问页面,页面即使https的。