HTTP基础

HTTP, TCP, IP 三者之间的关系

HTTP基础

在OSI网络模型中, HTTP是应用层的协议, TCP是传输层的协议, IP是网络层的协议.

一个完整的HTTP请求过程

  1. 用户输入URL
  2. DNS域名解析
  3. TCP三次握手
  4. HTTP请求/响应
  5. TCP四次挥手

客户端并不是直接与目标服务器创建连接, 而是先与代理服务器创建连接, 接着根据代理服务器所使用的代理协议, 请求对目标服务器创建连接, 或者获得目标服务器的指定资源(如:文件). 下文所提到的缓存服务器是代理服务器的一种, Java开发最常见的代理服务器就是Nginx.

无状态的HTTP

HTTP是一种不保存状态的协议, 即无状态协议. 使用HTTP协议, 每当有新的请求发送时, 就会有对应的新响应产生. 协议本身并不保留之前一切的请求或响应报文信息. 这种无状态的协议可减少服务器的CPU及内存资源的消耗, 但却无法满足某些业务场景, 如web页面的登录认证, 不能每次跳转页面都要再次登录, 于是引入了Cookie技术.

Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态, 当客户端第一次发送请求到服务器时, 服务器会生成一个Cookie, 放在响应报文的Set-Cookie首部字段中发送给客户端. 当下次客户端再往该服务器发送请求时, 客户端会自动在请求报文中加上Cookie, 服务器端发现客户端发送过来的 Cookie 后, 会去检查究竟是从哪一个客户端发来的连接请求, 然后对比服务器上的记录, 最后得到之前的状态信息.

HTTP1.0和HTTP1.1之间的区别

HTTP基础

如上图所示, HTTP1.0是短连接, 每进行一次HTTP通信就要断开一次TCP连接. 这种短连接的方式增加了通信量的开销, 为了解决这种问题, HTTP1.1想出了持久连接的方法. 持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态. 如下图所示:

HTTP基础

持久连接的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销, 减轻了服务器端的负载. 另外, 减少开销的那部分时间, 使HTTP 请求和响应能够更早地结束, 这样 Web 页面的显示速度也就相应提高了.

HTTP报文结构

HTTP报文分为请求报文和响应报文, 他们的结构如下图所示:
HTTP基础

这里访问下CSDN博客页面, 查看HTTP报文结构:
HTTP基础
HTTP基础

请求行

包含用于请求的方法, 请求 URI 和 HTTP 版本.

HTTP基础

状态行

包含表明响应结果的状态码, 原因短语和 HTTP 版本.
HTTP基础

通用首部字段
HTTP基础

(1)Cache-Control

通过指定首部字段 Cache-Control 的指令, 就能操作缓存的工作机制. 指令的参数是可选的, 多个指令之间通过“,”分隔. 首部字段Cache-Control 的指令可用于请求及响应时.

Cache-Control: private, max-age=0, no-cache

Cache-Control指令表:

HTTP基础
HTTP基础

  • public和private指令
    当指定使用 public 指令时, 则明确表明其他用户也可利用缓存.当指定 private 指令后, 缓存服务器会对该特定用户提供资源缓存的服务, 对于其他用户发送过来的请求, 代理服务器则不会返回缓存.
  • no-cache
    客户端发送的请求中如果包含 no-cache 指令, 则表示客户端将不会接收缓存过的响应. 于是, “中间”的缓存服务器必须把客户端请求转发给源服务器. 如果服务器返回的响应中包含 no-cache 指令, 那么缓存服务器不能对资源进行缓存. 源服务器以后也将不再对缓存服务器请求中提出的资源有效性进行确认, 且禁止其对响应资源进行缓存操作.
  • max-age
    当客户端发送的请求中包含 max-age 指令时, 如果判定缓存资源的缓存时间数值比指定时间的数值更小, 那么客户端就接收缓存的资源. 另外, 当指定 max-age 值为 0, 那么缓存服务器通常需要将请求转发给源服务器. 当服务器返回的响应中包含 max-age 指令时, 缓存服务器将不对资源的有效性再作确认, 而 max-age 数值代表资源保存为缓存的最长时间.

(2)Connection

Connection 首部字段主要用来管理持久连接. HTTP/1.1 版本的默认连接都是持久连接(Connection: Keep-Alive), 当服务器端想明确断开连接时,则指定Connection 首部字段的值为 Close(Connection: close).

请求首部字段

HTTP基础

响应首部字段

HTTP基础

实体首部字段

HTTP基础

为 Cookie 服务的首部字段

HTTP基础

(1)Set-Cookie

当客户端第一次连接服务器时, 服务器会生成Cookie, 并发送给客户端. 下面的表格列举了 Set-Cookie 的字段值:
HTTP基础

  • expires
    当省略 expires 属性时, 其有效期仅限于维持浏览器会话(Session)时间段内.
  • path
    Cookie 的 path 属性可用于限制指定 Cookie 的发送范围的文件目录.
  • HttpOnly
    Cookie 的 HttpOnly 属性是 Cookie 的扩展功能, 它使JavaScript 脚本无法获得 Cookie. 其主要目的为防止跨站脚本攻击(Cross-sitescripting,XSS)对 Cookie 的信息窃取.

(2)Cookie

当客户端再次连接服务器时, 就会在请求中包含从服务器接收到的 Cookie.

HTTPS

HTTP的缺陷如下:

  • 通信使用明文(不加密), 内容可能会被窃听
  • 不验证通信方的身份, 因此有可能遭遇伪装
  • 无法证明报文的完整性, 所以有可能已遭篡改

HTTPS采用SSL协议(Secure Socket Layer)解决了HTTP的上述缺陷, SSL协议的安全机制如下:

  • 数据加密传输
  • 身份认证机制
  • 报文完整性检查

HTTPS 只对报文主体加密.

SSL的原理

数据加密传输

首先介绍两种加密方式, 共享**加密和公开**加密, SSL采用的是两者并用的混合加密机制.

(1)共享**加密

加密和解密同用一个**的方式称为共享**加密(Common keycrypto system), 也被叫做对称**加密. 但共享**加密存在的问题是如何把**安全地转交给对方.

(2)公开**加密

公开**加密使用一对非对称的**. 一把叫做私有**(private key), 另一把叫做公开**(public key). 顾名思义, 私有**不能让其他任何人知道, 而公开**则可以随意发布, 任何人都可以获得. 使用公开**加密方式, 发送密文的一方使用对方的公开**进行加密处理, 对方收到被加密的信息后, 再使用自己的私有**进行解密. 利用这种方式, 不需要发送用来解密的私有**, 也不必担心**被攻击者窃听而盗走.

(3)混合加密机制

公开**加密的性能是要低于共享**加密的, 所以 SSL 充分利用两者各自的优势, 采用共享**加密和公开**加密两者并用的混合加密机制, 通过公开**加密方式来转交共享**, 然后在报文通信阶段使用共享**加密方式.

身份认证机制

在通过公开**加密方式来转交共享**时, 发布公开**的服务器身份可能被伪装, 比如客户端收到的公开**可能来自于另一个"伪装"服务器. SSL的身份认证机制可以解决该问题:

服务器的运营人员向数字证书认证机构(CA,CertificateAuthority)申请数字证书, 数字证书是一个包含服务器的公钥及其身份信息的文件, 证明了服务器与公钥的关联性. 然后服务器将这份数字证书发送给客户端, 客户端通过CA验证该证书的真实性, 验证通过后就获得了服务器的公钥, 接下来服务器通过公开**加密方式转交给客户端共享**, 最后通过共享**加密报文进行通信.

客户端验证数字证书的真实性实际上是验证CA的数字签名, 验证数字签名就需要CA的公开**, 而CA如何安全的转交自己的公钥又是一件困难的事情, 所以大多数浏览器开发商发布版本时, 会事先在内部植入常用CA的公开**.

数字签名是如何验证的呢?
Alice使用自己的私钥对一段固定的信息加密后发给Bob, Bob利用Alice的公钥解密, 如果解密结果与固定信息相同, 那么就能够确认信息的发送者为Alice.

报文完整性检查

SSL使用MAC算法来保证报文的完整性, MAC算法是在**参与下的数据摘要算法, 能将**和任意长度的数据转换为固定长度的数据. MAC算法验证报文完整性的过程如下:

发送者在**的参与下, 利用MAC算法计算出消息的MAC值, 并将其加在消息之后发送给接收者. 接收者利用同样的**和MAC算法计算出消息的MAC值, 并与接收到的MAC值比较. 如果二者相同, 则报文没有改变, 否则, 报文在传输过程中被修改, 接收者将丢弃该报文.

这里的**使用的是共享**.