HTTP与HTTPS

HTTP协议用于用于客户端和服务器通信,请求访问资源的一端称为客户端,而提供资源响应的一端称为服务端,HTTP协议使用URI定位互联网上的资源,当客户端请求访问资源而发送请求时,URL需要将作为请求报文中的请求URL包含在内

URL

统一资源定位符
http://user:pass@www.example.jp:80/dir/index.htm?uid=1#ch1
http: 协议名
user:pass: 登录信息
www.example.jp: 服务器地址
80: 端口号
dir/index.htm: 带层次的路径名
uid=1: 查询字符,一个个key=val形式的键值对,并且键值对之间用&符号进行间隔
ch1: 片段标识符

eg:
https://www.bing.com/search?q=C%2B%2B&qs=n&form=QBLH&sp=-1&pq=&sc=0-0&sk=&cvid=553C64EAE262401D94DD4794F3A33CFF
我们可以看到,上面的url格式中,有一些字符,比如/?:等这些字符在url中有着特殊的含义,我们不可以随便的使用,某个参数中需要带有这些特殊字符,就必须先对特殊字符进行转义,转码的字符转为16进制,编码成%XY格式,"+" 被转义成了 “%2B”

HTTP请求格式

img1

首行: [方法] + [url] + [版本]
Header: 请求的属性,冒号分割的键值对,每组属性之间使用\r\n分隔,遇到空行(连续两次\r\n)表示Header部分
结束
常见属性:
Host: 表示访问主机名,也就是ip地址的别,即域名
Connection: 长连接开关
Content-Length: Body长度
Cache-Control: 缓存时间
Upgrade-Insecure-Requests: 请求升级
Content-Type: 正文数据类型
User-Agent: 操作系统和浏览器信息
Accept: 用户代理可处理的类型
Referer: 跳转信息
Accept-Encoding: 内容编码,内容编码后的实体由客户端接收并负责解码
Accept-Language: 客户端语言
Cookie: 用来保存一个从服务器返回回来的字符串,并且保存到本地,下一次访问同一个网站,会将这个信息带回去
Body: 空行后面的内容都是Body,允许为空字符串,如果Body存在,则在Header中会有一个Content-Length属性来标识Body的长度

请求方法

GET: 获取资源,请求访问已被URI识别的资源,经服务器端解析后返回
POST: 传输实体主体
PUT: 传输文件,自身不带验证机制,任何人都可以上传,存在安全问题,需要配合Web应用程序的验证机制,或架构设计采用REST标准的同类Web网站
HEAD: 获得报文首部
DELETE: 删除文件
OPTIONS: 询问支持的方法
TRACE: 通过属性Max-Forwards追踪路径
CONNECT: 要求用隧道协议连接代理

HTTP响应格式

img2

首行: [版本号] + [状态码] + [状态码解释]
Header: 响应属性
常见属性:
Sever: HTTP服务器安装信息
Content-Type: text/html表示body的格式是一个xml的文本格式,charset说明字符集为utf-8
Content-Length: Body部分的字节数
Location: 令客户端重定向到指定的URL
Transfer-Encoding: 传输内容编码,如分块传输每一块都会用十六进制来标记块的大小, 而实体主体的最后一块会使用0\r\n
Set-Cookie: 和请求中的Cookie对应,服务器利用Set-Cookie向客户端返回用来表示身份信息的的字符串,下次访问时就会重新带入,避免再次登录
Body: 如果服务器返回了一个html页面,那么html页面内容就是在body中

状态码

img3

200 OK 表示从客户端发来的请求在服务器端被正常处理
204 No Content 服务器接收的请求已成功处理, 但在返回的响应报文中不含实体的主体部分
206 Partial Content 客户端进行了范围请求,服务器成功执行了这部分的GET请求。响应报文中包含由Content-Range指定范围的实体内容
301 Moved Permanently 永久性重定向表示请求的资源已被分配了新的URI,以后应使用资源现在所指的URI。也就是说,如果已经把资源对应的URI保存为书签了,这时应该按Location首部字段提示的URI重新保存
302 Found 临时性重定向
304 Not Modified 服务器端允许请求访问资源,但未满足条件的情况
400 Bad Request 请求报文中存在语法错误
401 Unauthorized 表示发送的请求需要有通过HTTP认证的认证信息
403 Forbidden 对请求资源的访问被服务器拒绝
404 Not Found 无法找到请求的资源
500 Internal Server Error 服务器端在执行请求时发生了错误
503 Service Unavailable 服务器暂时处于超负载或正在进行停机维护
504 Gateway Timeout 网关超时

Cookie

HTTP是一种不保存状态,即无状态的协议。HTTP协议自身不对请求和响应之间的通信状态进行保存,这是为了更快地处理大量事务,确保协议的可伸缩性,可减少服务器的CPU及内存资源的消耗而特意把HTTP协议设计成如此简单的,但是针对一些场景,需要继续保持登录状态,于是引入了Cookie技术,有了Cookie再用HTTP协议通信,就可以管理状态了
如果,客户端发送的报文中无Cookie,则服务器生成一个Cookie,通过Set-Cookie的首部字段信息,通知客户端保存Cookie。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入Cookie值后发送出去,服务器端发现客户端发送过来的Cookie后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到之前的状态信息

持久连接

HTTP协议的初始版本中,由于当年都是些容量很小的文本传输,每进行一次HTTP请求响应就要断开一次TCP连接,随着HTTP的普及,文档中包含大量图片的情况多了起来。比如,使用浏览器浏览一个包含多张图片的HTML页面时,发送请求访问HTML页面资源的同时,也会请求该 HTML页面里包含的其他资源,每次的请求都会造成无谓的TCP连接建立和断开,增加通信量的开销所以1.0版本时候,部分厂商提出了持久连接,只要任意一端没有明确提出断开连接,则保持TCP连接状态。
HTTP/1.1 中,所有的连接默认都是持久连接,持久连接使得多数请求以管线化方式发送,从前发送请求后需等待并收到响应,才能发送下一个请求。管线化技术出现后,不用等待响应亦可直接发送下一个请求,做到同时并行发送多个请求,不需要一个接一个地等待响应

HTTP存在的问题和解决方法

由于通信使用明文,所以内容可能会被窃听,而且不验证通信方的身份, 有可能遭遇伪装,还无法证明报文的完整性, 有可能已遭篡改。

解决方法:

  1. 通信加密
    HTTP协议中没有加密机制,但可以通过和SSL或TLS的组合使用,加密HTTP的通信内容,用SSL建立安全通信线路之后, 就可以在这条线路上进行HTTP通信了
  2. 内容加密
    客户端需要对HTTP报文进行加密处理后再发送请求img4

但是单纯的加密的不够的,还需要身份验证,如果不论谁发送过来的请求都会返回响应,会存在很多隐患,有可能响应给伪装的Web服务器或者客户端,无法确定正在通信的对方是否具备访问权限,无意义的请求也会照单全收(无法阻止DOS攻击)
所以SSL还使用了一种被称为证书的手段,可以确认对方,证书由值得信任的第三方机构颁发,用以证明服务器和客户端是实际存在的。另外,伪造证书从技术角度来说是异常困难的一件事。所以只要能够确认通信方(服务器或客户端)持有的证书,即可判断通信方的真实意图,另外,客户端持有证书即可完成个人身份的确认,也可用于对Web网站的认证环节

但这还存在一些问题,HTTP协议无法证明通信的报文完整性,因此,在请求或响应送出之后直到对方接收之前的这段时间内,没有任何办法确认, 发出的请求/响应和接收到的请求/响应是前后相同的img5
所以我们可以用MD5和SHA-1等散列值校验的方法,以及用来确认文件的数字签名方法,但这些方法也依然无法百分百保证确认结果正确,PGP和MD5本身被改写的话,用户是没有办法意识到的,因此仅靠HTTP确保完整性是非常困难的

HTTPS

HTTP+ 加密 + 认证 + 完整性保护=HTTPS

HTTPS是身披SSL外壳的HTTP,HTTP先和SSL通信,再由SSL和TCP通信
img6

加密
对称密钥加密:加密和解密同用一个密钥,这种方式必须将密钥也发给对方,但是密钥若能安全发送,那数据也能到达

对非对称密钥加密:使用公开密钥加密方式,发送密文的一方使用对方的公开密钥进行加密处理,对方收到被加密的信息后, 再使用自己的私有密钥进行解密。利用这种方式,不需要发送用来解密的私有密钥, 也不必担心密钥被攻击者窃听而盗走,但是处理速度慢

混合加密机制:HTTPS采用对称加密和非对称加密并用的混合加密机制,在交换密钥环节使用公开密钥加密方式,之后的建立通信交换报文阶段则使用共享密钥加密方式

认证
为了解决身份验证问题,HTTPS中使用数字证书认证机构和其相关机关颁发的公开密钥证书。
服务器的运营人员向证书认证机构提出公开密钥的申请。证书认证机构在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入证书后绑定在一起,服务器会将这份由认证机构颁发的证书发送给客户端,以进行公开密钥加密方式通信,当客户端接收到服务器发送的公钥证书的时候,就会向证书认证机构来验证数字签名是否正确,来判断该公钥是否遭到替换,确保了公钥的真实性

HTTPS通信步骤

img7

  1. 客户端通过发送Client Hello报文开始SSL通信。 报文中包含客户端支持的SSL的指定版本、 加密组件列表(所使用的加密算法及密钥长度等)
  2. 服务器可进行SSL通信时,会以Server Hello报文作为应答。和客户端一样,在报文中包含SSL版本以及加密组件。服务器的加密组件内容是从接收到的客户端加密组件内筛选出来的
  3. 服务器发送Certificate报文。报文中包含公开密钥证书
  4. 最后服务器发送Server Hello Done报文通知客户端,最初阶段的SSL握手协商部分结束
  5. SSL第一次握手结束之后,客户端以Client Key Exchange报文作为回应。报文中包含通信加密中使用的一种被称为Pre-master secret的随机密码串。该报文已用步骤3中的公开密钥进行加密
  6. 接着客户端继续发送Change Cipher Spec报文。该报文会提示服务器,在此报文之后的通信会采用Pre-master secret密钥加密
  7. 客户端发送 Finished 报文。该报文包含连接至今全部报文的整体校验值。这次握手协商是否能够成功,要以服务器是否能够正确解密该报文作为判定标准
  8. 服务器同样发送Change Cipher Spec报文
  9. 服务器同样发送Finished报文
  10. 服务器和客户端的Finished报文交换完毕之后,SSL连接就算建立完成。当然,通信会受到SSL的保护。从此处开始进行应用层协议的通信,即发送HTTP请求
  11. 应用层协议通信,即发送HTTP响应
  12. 最后由客户端断开连接。断开连接时,发送close_notify报文。上图做了一些省略,这步之后再发送TCP FIN报文来关闭与TCP的通信

在上面的流程中,应用层发送数据的时候会附加MAC报文摘要,MAC能够查知报文是否遭受到篡改,从而让保护报文的完整性

img8

HTTPS也存在一些问题,那就是当使用SSL时,通信速度慢,大量消耗CPU及内存等资源,导致处理速度变慢(解决方法SSL专用服务器)