http协议(HyperText Transfer Protocol - 超文本传输协议):
在网络层中被广为人知的协议,想必没有学过计算机的人都知道http是有关网站,网络的,那么究竟其中有哪些东西是需要计算机相关人员掌握的,为何又叫做协议。
所谓协议,正是为了区分懂的人和不懂的人,换言之,协议只对遵守协议的人起作用,协议也只为遵守协议的人服务,对于不懂得遵守协议的人,协议自然而言就发挥不了其作用,那么之于互联网行业,懂得遵守协议的人也就是程序员了,协议由程序员编写,由程序员维护,也自然而然只有程序员懂得如何遵守协议,如何使其为己所用,那么对于不懂的人来说,也就是普通人,只能“傻傻”的使用,其中的细节,发展历史,也就没办法知道了,总之,协议是为了规范程序员与程序员在操作网络网页时能更加规范,更加有序。
既然我们讨论的话题是网络协议,那么首先要问一个问题,什么是网络,网络之于我们的生活中的哪里?如何发现它?如何学习它?
对于已经定义的网络概念:网络也是一个栈结构,网络协议栈,由不同的层构成不同的层面,用来完成网络传送接受不同的子功能,它是一个软件,贯穿整个体系结构,属于操作系统的一部分。
什么是网络:
网络大致分为五层,由上到下分别为:应用层,传输层,网络层,数据链路层,物理层。
今天要讨论的http协议和https协议就是应用层最重要的协议,所谓应用层就已经是涉及到用户使用应用时的层面了,也就是大家平常在浏览网页时经常看到的网址前缀:https://...
协议:
在对网络有了大概理解后,让我们再次回到协议的概念,由于计算机之间的传输媒介是广电信号和电信号,通过频率的强弱来表示0 1这样的信息,要想传递不同的信息,就需要收发双方约定好数据格式,所以协议也就是一种约定,一种程序员根据文档或者自身喜好设定的决定。
HTTP协议:
身处应用层的首要协议http协议,负责与其下层:传输层进行沟通,所以在此又要为大家引出另一个概念,大家可能平时在使用网络收发数据时,以为数据是直接通过网络 -> 网络,其实不然,信息在用户的应用层编辑好,需要向下交付,经过不同层的不同协议(每层都有每层的协议),在数据的基础上打上各层的报头再发出,发出后对方再由下到上依次解包,最后拿到需要的数据。
至此,我们正式引出http的概念,既然作为应用层的协议,自然就离不开和用户打交道,http协议和https协议在全世界主流浏览器中已经是必须要安装遵守的协议,我们平时在网络中搜索的图片,文章,视频等等,这些都被称为“资源”。
百度一下,你就知道全球领先的中文搜索引擎、致力于让网民更便捷地获取信息,找到所求。百度超过千亿的中文网页数据库,可以瞬间找到相关的搜索结果。https://www.baidu.com/?tn=15007414_8_dg/ 我们以百度的网址为例,大家有没有发现网址的构成就像是电脑中的文件路径一样,没错,在操作系统中万物皆文件,所以网络资源也是文件,文件就存在百度的服务器中。
我们知道服务器的后台大多都是Linux系统支持的,由公网IP确定唯一一台机器,port确定机器上的一个进程,IP+port就能确定一台机器上的唯一一个进程,而我们所访问的“资源”,都是一定存在于网络中一台Linux机器上,而Linux或传统操作系统保存资源的方式都是以文件的形式保存的,单Linux系统标识一个资源的方式称之为路径。
所以IP+Linux路径,可以唯一确定一个资源。
而IP通常是以域名的方式呈现的,路径可以通过目录名+'/'找到。
encode和decode:
我们有时候会发现当在网站中搜索某些中文中,浏览器会自动给我们识别成其他的字符,例如当我们在浏览器中搜索C++时,C会正常显示,而++则会被处理成%2B%2B,这就跟http的对于编码的规范有关了
2B代表+,由%区分一个字符,所以C++也就被解码成C%2B%2B。
HTTP协议的基本格式:
当我们在请求一个网络资源时,通常来说就是上网的过程中给,服务器端如何知道有人在访问它呢?它又如何知道用户访问的是它哪里的资源?又如何返回?这就跟http协议的基本格式有关了。
http协议无论是请求还是相应,都是以'\n'为分隔,也就是按照以行为单位来构建请求或者响应的,基本都是3或4部分构成。
http request:由请求方法为首+请求方请求的url,加上http的协议的版本构成第一部分,与这次请求有关的相关属性,像是请求资源的大小,请求的状态,报文的实际大小等等构成第二部分,再第三部分前需要一个空行来分割,空行后就是用户请求的正式报文了。
http response:由http版本+此次响应的状态码+状态码的描述构成第一部分,第二部分和请求的格式大致类似,紧接着也是一个空行分割,之后由正文组成的报文构成第三部分。
所以不难发现,http是利用空行来分隔报文,也叫做有效载荷与报头的,有效载荷中承载的就是用户要访问的数据或服务器向用户返回的数据!所以http在读数据和发数据时,会将整体的数据看作一个大字符串,将字符串封装好,加上http独有的报头,向下交付,由传输层的tcp/udp协议的发送/接受缓冲区来处理。
Content-Length属性:
接下来我们来了解一个处于http报文第二部分其中的一个属性:Content-Length,只翻译就能得知此属性代表了文本的长度,所谓文本的长度也就是报文(有效载荷)的长度。
当我们有一批数据由下层的tcp给我们传来,http需要将其正确地读到并正确地显示,不要将下一次要读的数据提前拿到,那么如何保证正确呢?这是Content-Length就发挥了它的作用,它标识了正文有多少个字节,http就是通过它来保证每次读到的报文只属于本次http请求/响应,同时,根据空行能够做到将报头和有效载荷进行分离,如果此次请求/响应没有有效载荷,也就没有Content-Length这个属性。
GET方法和POST方法:
了解过http的报文格式后,接下来了解一下http协议在收收发数据时最常用的两个方法:GET&POST。
如果我们用Linux来接收一个http请求,就会看到一个完整的http报文,在上文的http request中也提到了,第一部分的首,就是由http的请求方法。所以请求方法之于http协议如何拿到参数是非常重要的。
这就是一个较为完整的http请求,可以看到它用的GET方法,访问的是网站的'/',那么之前是说请求方法后跟的是访问资源的Linux资源路径吗?单单一个'/'又代表了什么意思?难道是要访问根目录?要将根目录的全部内容返回吗?肯定不是,'/'代表了不请求服务器的任何资源,只是访问该网站的首页而已,通常也就是index.html,如果要访问主页的其他内容,只需要在/后面加上指定的文件路径即可。
GET方法和POST方法的基本格式:
那么二者有何区别呢?同样为http的请求方法,GET方法在提交参数上和POST有明显不同,例如我们要在网站中输入用户名和密码,而GET方法是直接将用户输入的参数通过url提交,而url是有大小限制的,也就是其会显示在网页中,而POST则是通过正文提交,不会显示在网页中,正文也没有大小限制,所以相比GET方法,POST方法对于用户隐私信息的保护是要更加私密,所以如果提交的参数不敏感,数量非常少,可以采用GET,反之就采用POST。
但是我们不要单纯的认为私密就是安全,当一个资源被反派拿到时并不可怕,就算拿到也对其没有访问的办法才叫安全,所以在网络如此发达现在,我们都可以通过一些软件抓到自己访问浏览器的报文,更别说一些黑客了,想要更加安全,就必须要对数据进行加密,为在网络中“裸奔”的数据穿上坚硬的盔甲。
HTTP常见的状态码:
突然提出状态码的概念,大家可能会一脸懵,对于状态码毫无概念,但是如果我说出一个大家很熟悉的状态码:404 NOT FOUND!大家肯定就会明白许多了,所谓状态码就是表示此次http收发的状态,通常是server端返回给client端,将请求结果正确地返回给用户。
那么常见的状态码有5类,分别代表了因为不同的错误导致的网页无法正确返回。
常见的状态码:200(OK), 404(NOT FOUND), 403(FORBIDDEN), 302(REDIRECT,重定向), 504(BAD GATEWAY)。
1开头:代表请求正在处理,2开头:请求处理完毕,3开头:重定向,需要附加操作,4操作:用户端出现错误,导致无法正确显示,5开头:服务端出现错误导致无法返回。
所以404状态码代表了用户端请求的资源不存在,并不是服务端本身的问题,是搜索者本身的问题。
而3开头的重定向状态码是有特殊含义的,比如一个网站在经过多年的运营后需要更换新的域名,而老用户并不知道新的域名,server会告诉浏览器接下里要去的新地址,Location,所以就会出现突然跳转到新网站的情况,或者在进入到需要登录的网站时,必须要在登录后才能正确显示网站主页,这些情况都属于重定向。
而重定向又分为临时重定向(302/307)和永久重定向(301),像改变域名就是永久重定向,不再跳转到旧网站,登录后显示主页就是临时重定向。
所以为了支持http的这些状态码,达成用户端和服务端的一致,就要要求浏览器要认识这些状态码,并在出厂时就要预装,并且达成一致。
Connection属性:
一般而言,一个大网页由许多个元素构成,而http/1.0版本采用的网络请求方案就是短链接的方式,所谓短链接就是用户端请求,服务端响应后算作一次连接,连接后即可断开链接,下次请求时再建立连接,http协议是基于tcp协议的,而tcp协议通信就是基于:建立连接 -> 传送数据 -> 断开连接。没一次的http request都要执行上述操作,这种上网方式对于很多年之前刚生成互联网时的上网需求可能还能处理,而现在肯定是不行了,有时候甚至在网上下一个文件就要几个小时,就要要求服务端和用户端长时间建立链接。
而Connection属性就表示了用户端和服务端建立链接的状态,只要服务端和用户端没有断开,Connection就一直处于:Keep Alive状态。
而http/1.1版本自然而然支持了长链接,通过减少tcp连接来达到提高效率的目的。
http协议常见的属性:
cookie和session:
不知道大家平时在上网时候有没有这种感觉:当我第一次访问网站时要求我输入密码,但是为什么在我第二次进入网站时,它会自动保持我上次的登录状态呢?为什么它知道我喜欢看什么?并针对我的喜好设计了很多相关推送?我的信息是如何被该网站拿到的?保存在哪里?可以删除吗?是否安全等问题。
而http协议本身是无状态的协议,并不记录历史请求和上下文信息,但这些问题并不需要http来解决,http需要做的只是做一些技术支持,来保证网站会有“记录会话”的功能。
该技术就是cookie+session:为了提高用户访问网站/平台的体验。
cookie:
1.之于浏览器,cookie是一个文件,里面保存了用户的私密信息。(文件版)
2.之于http协议,一旦网站对应有cookie,再发起任何请求的时候,都会自动在request种携带cookie信息。(内存版)
那么在cookie文件被盗取后,别人也理应能通过我的身份来访问验证本属于我的资源,甚至我的账号和密码,所以单纯使用cookie是肯定有很大安全隐患的。
session:
将用户的信息保存在服务端。
也就是说单单使用cookie虽然解决了保存会话的功能,但是用户的信息安全保证不了,依然会被世界各地的黑客用来作为攻击的对象,如何解决这个问题呢?就需要服务端做出措施,在用户将账号密码等私密信息输入进网站后,在server端为该用户创建文件,信息保存在服务端本地,形成单独的session文件,其中保存着用户的私密信息,并为该用户创建唯一的session_id,而client端只显示用户的session_id。这样一来server端依旧可以做到认识client端,也是一种会话保持的功能。
https协议(HyperText Transfer Protocol Secure - 超文本传输安全协议):
我们之前讨论了http协议是无状态的协议,在数据传送的过程中,虽然POST方法相对GET方法较为安全,但是数据依然不安全,如果有人设法拿到了我的正文信息,那么POST方法也将不再安全,而这种攻击技术在现实中一定是早已被人发现使用的,那么如何保证数据安全呢?https协议就应运而生。
我们先来了解http协议的基本结构,与http协议大致相同,最大的不同就是其真对保护信息安全设立的内嵌协议:TSL/SSL。
SSL:(Secure Socket Layer,安全套接字层),位于可靠的面向连接的网络层协议和应用层协议之间的一种协议层。SSL通过互相认证、使用数字签名确保完整性、使用加密确保私密性,以实现客户端和服务器之间的安全通讯。该协议由两层组成:SSL记录协议和SSL握手协议。
TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。该协议由两层组成:TLS 记录协议和 TLS 握手协议。
简而言之,https在传输数据时不再简单地传输数据,而是需要对数据进行加密,像是钥匙和锁的关系一样,想要开锁,那么另一端就必须要有钥匙,也可以用C++代码来模拟一下加锁和解锁的过程:
可以看出当一个数据经过按位与后的结果就是加了密的数据,而按位与操作只有对端的机器知道要如何破解,其中被任何人拿到都无从下手,也就达成了安全的概念。
对称加密和非对称加密:
我们知道https协议在传输数据相较http协议要加密了,那么如何加密呢?加密算法究竟该如何设计才能保证收发两端能够安全正确破解,而中间任何人拿到都无法操作呢?其中引出这两种方法:
1.对称加密:
将所有机器都预装密钥,也就是用来解锁的钥匙,这样一来服务端在发送数据时只需要发送经过加密的数据,而所有机器都可以进行解锁。
这种方法显然行不通,任何人都有,和任何人都没有又有什么区别呢?还是保证不了数据的安全,数据只是形式上确实被加密了,但是安全依然是问题。
2.非对称加密:
第一次client向server发送https请求,server将密钥交付给client,client端将密钥和数据进行加密操作,再传回server,而server知道该如何破解,经过破解拿到了数据,这种方式保证了单向的数据传输安全,也就是client->server这个方向是安全的。
但是反向过来就不再安全,server发送的数据经过其私有的密钥加密后发给client,但是公钥在第一次client访问时就已经拿到了,也就是说想要攻击sever的数据,只需要访问一次server,拿到其公钥,本质上又回到了对称加密,所以还是无法保证数据安全。
那么既然对称加密不安全,非对称加密只能保证单向安全,那么如果我们采用两次非对称加密的单向传输,是不是就可以保证双向安全呢:
在通信之初双方交换的公钥,client拿着要发送的数据和对方的公钥对报文进行加密,发送给server,由于server之前已经获得了client的公钥,所以自然而然就可以用自己的私钥解锁client的数据包,再向上交付,将client要请求的数据与自己的私钥进行加锁,再发送回client,这样一来双方既可以加密传输,也可以解密收取,也保证了双方通信的安全。
但是这样的做法虽然能大概率保证数据的安全,但是数据依然有被盗取的可能性,所以要相信这个世界上人外有人,天外有天,而且双方之前频繁进行非对称加密的算法是非常耗费时间的,反之对称加密是比较节省时间的。
所以实际上的方案是:非对称+对称方案
在密钥协商阶段采取非对称算法,在通信阶段采取非对称算法
了解了对称加密和非对称加密后,来假设这样一种情况,在client和server之间出现了一个中间人,既然client都可以获取server的公钥,那么中间人相对于server也身为client并拿到了其公钥,中间人再将这个公钥用自己的公钥加密交付给client,而client并不知道公钥被修改了,拿着自己的私钥进行解密,在交付给server,但实际上又被中间人给截胡,再用自己的私钥解密,发给server,那么这样一来中间人就拿到了client和server的公钥,在接下来双方使用对称算法时,中间人都可以对数据进行拷贝,加密解密,对数据进行篡改,如此就实现了对数据的监测。
所以出现上述问题的本质是client并不清楚自己收到的公钥是server发来的还是中间人发来的,它只知道这是公钥,就无脑对其进行对数据的加密,但是其实这套操作完全暴露在中间人的视野里。
CA机构:
那么解决办法就是将钥匙权威化,由一个权威的机构统一分发公钥,并且只要该网站合法,经过CA证书机构认证后,会拿着该网站的基本信息,域名,私钥等,为该网站创建证书,形成单独的数据指纹,并且CA机构会用自己的私钥对其进行加密,形成专属于该网站的数据签名,其他人无法修改,CA机构的私钥只有自己知道,也就是说全世界只有CA机构能重新生成数字签名,并且在接下来的client&&server收发的过程中,要先将server的CA证书发送给client,期间如果被中间人捕捉到,也并不担心会被修改。