图解HTTP
HTTP历史
WWW,即Web
-
1989年,HTTP诞生;最初的设计理念是:界诸多文档之间相互关联形成的超文本,连成可以相互参阅的WWW。
-
现在WWW的三项核心构建技术:
- HTML,超文本标记语言;作为页面语言
- HTTP,超文本传输协议;作为传输协议
- URL,统一资源定位符;作为资源获取地址
HTTP版本发展
HTTP 1.0
- HTTP作为正式标准公布:1996.5,命名为HTTP1.0
HTTP 1.1
- HTTP 1.1在1997.1公布,现在的修订版是RFC2616
HTTP特点
HTTP 1.0 非持久连接
- 早期版本非持久连接是指:每进行一次HTTP通信,都会断开一次TCP连接。缺点是HTML页面资源内容多的时候会增加通信量。

HTTP 1.1 持久连接
- HTTP 1.1 引入了持久连接并设为默认选项:keep-alive。只要任一端没有明确提出断开连接,就保持连接。减少TCP重复连接和断开的开销
Pipeline
-
没有pipeline时,发送了请求,需要等待收到响应才能发送下一个请求。
-
持久连接使得pipeline成为可能,即并行发送多个请求,更加节省时间。
使用Cookie的状态管理
-
HTTP是无状态的,不对之前发生过的请求和响应状态进行管理,服务端也不保存客户端信息。
-
Cookie对无状态的HTTP进行状态化。
Cookie工作原理
- 用户初次向服务器发送报文,服务器web进程为其产生一个唯一的Cookie识别码,并以此为索引,在服务端后端数据库中创建一个项目,记录用户访问的各种信息。
- 服务端发送的响应报文内的叫做Set-Cookie的header字段,通知客户端保存cookie;下次客户端发送请求时,会在请求报文中加上cookie值。服务端收到后会对比记录,了解到是哪客户端发来的。

HTTP报文
结构
报文首部 + 空行(CR+LF,意思是十六进制的回车+换行符)+ 报文主体。(二者由第一个出现的空行来区分)

编码提升传输速率
传输时编码可以提高传输速率,但要在计算机内完成,消耗CPU资源。
- 压缩传输的内容编码:
- gzip(GNU zip)
- compress (UNIX系统的标准压缩)
- deflate (zlib)
- identity
分割发送
传输大容量数据时,会将实体主体部分分割成多个块。接收端解码、恢复。
发送多种数据的多部分对象集合
- 发送的同一份报文中可能含有多种类型的实体,文本、图片等。
- HTTP报文使用多部分对象集合时,需要在首部字段中加上Content-type;并使用boundary字符串来划分多类实体。
获取部分内容的范围请求
- 也就是断点续传:比如对于一份10000字节的资源,使用范围请求,可以只请求5000-10000字节的内容。
- 请求报文用首部字段Range来制定资源的byte范围;响应报文用206 Partial Content作为状态码,并且加上Content-type中国标明multipart/byterange
内容协商
- 客户端和服务端就响应的资源内容进行交涉,给客户端提供最合适的资源。比如页面语言、encoding等。
HTTP状态码
类别
- 1xx
Informational:接收的信息正在处理
- 2xx
Success:请求正常处理完毕
- 3xx
Redirection:重定向,意味着需要附加操作以完成
- 301:永久重定向
-
302:临时重定向
-
4xx
Client Error:服务器无法处理请求
- 400 BadRequest:表示请求报文中语法错误
- 401 Unauthorized:身份未认证或者认证失败
- 403 Forbidden:表示请求被服务器拒绝了,一般是会涉及访问权限问题,比如未授权的源IP的访问。
-
404 NotFound:请求的资源服务器上没找到;有时服务端拒绝请求但不想告诉你理由也能用。
-
5xx
Server Error:服务器处理请求出错
- 500 Internal Server Error
- 503 Service Unavailable:标明服务器暂时处于超负荷或者维护,暂时无法处理请求。、
与HTTP协作的Web服务器
用单台主机实现多个域名
单台服务器开启Virtual Host,就能即使在物理层面只有一台服务器,但是可以有多个主机名和域名,提供多个Web站点供访问。
通信数据转发程序
代理、网关、隧道
代理
-
基本行为就是接收客户端请求,转发给其他服务器,不会改变请求URI
-
每次转发都会加上via字段(via:proxy1)
-
使用代理的理由有:利用缓存技术减少网络中的流量;组织内部针对特定网站的访问控制;获取访问日志等
-
代理基本分类:
-
缓存代理
代理服务器作为缓存服务器,保存请求资源的缓存,返回给客户端。
-
透明代理
转发请求或响应时,不对报文做任何修改。
网关
- 利用网关能将HTTP协议转化为非HTTP协议。比如智能家居连接网关将各种非HTTP信号转化为HTTP信号发送给Internet。
隧道
- 建立起一条与其他服务器的通信线路,届时使用SSL等加密通信,不改变HTTP请求,直接转发;便于实现远距离通信。
缓存
服务器缓存
客户端缓存
缓存具有有效期,会向服务器确认缓存是否需要更新。
HTTP首部

请求报文组成

响应报文组成

- 通用首部字段:请求和响应都可以使用
- 实体首部字段:补充一些资源内容更新时间等与实体有关的信息。
HTTP1.1通用首部字段
Cache-control控制缓存的相关字段
- public、private
源服务器对缓存服务器做的规定
-
public:其他用户也可以用该份缓存;private:只能给这个请求的特定用户发送缓存。
-
no-cache
目的是防止接收到过期的缓存内容。
-
如果是客户端请求内容:则要求缓存服务器不能直接将缓存返回过来;缓存服务器会向源服务器发送请求验证缓存有效期。
-
如果是服务端响应内容:则要求缓存服务器不能缓存该相应内容。
-
no-store
当使用no-store时,按时请求或响应中包含机密信息。该指令规定不能保存为缓存
[!warning] 注意
no-cache和no-store的区别:no-cache只是确保不接收过期的缓存,而no-store才是不能缓存。
请求首部字段
authorization
- 用来告知服务器,用户代理的认证信息/证书值。
Host
- 同一个服务器,通过虚拟主机运行了多个web app,域名不同,但是是在同一个IP上;使用首部字段Host来区分不同的主机名和端口号。
- Host首部字段,在HTTP 1.1中,是唯一一个被要求必须包含在请求内的首部字段。
User-Agent
- 创建请求的浏览器和用户代理名称;如果经过了代理,中间也有可能被添加上代理服务器的名称。
响应首部字段
Age
- 告知客户端,源服务器在多久前创建了响应。字段单位为秒
Etag
- Etag是服务器资源的唯一性标识,每一份资源都有Etag;当资源更新的时候,可能URI没变,但是ETag会改变。
- 告知客户端,资源的实体标识。有时候,不同的资源的URI是相同的,比如中文版和英文版的网页,要靠ETag来分辨;当遇到连接中断再连接的时候,都会按照ETag的值来制定资源。
- ETag分为强ETag和弱ETag
Location
- 可以将接收方引导至某个与先前请求URI位置不同的资源。
- 一般该字段会配合3xx:Redirection的响应,提供重定向的URI。
Server
- 告知服务器上HTTP服务器应用程序的信息
WWW-Authenticate
- 告知客户端用于访问指定资源的认证方案(Basic or Digest)
- 状态码401 Unauthorized的响应中,会带上WWW-Authenticate首部字段。
实体首部字段
补充实体部分的相关信息。
为Cookie服务的首部字段
用户识别及状态管理。web网站为了管理用户的状态会通过浏览器,把一些数据临时写入用户的计算机内。接着用户带cookie访问该网站会被识别出来。
HTTPS
背景
-
HTTP的隐患:服务器伪装、客户端伪装、无法身份验证、照单全收无意义的请求。
-
HTTP + 加密 + 认证 + 完整性保护 = HTTPS
-
HTTPS只是通信接口采用SSL和TLS代替;

- HTTPS使用SSL和TLS,SSL最开始是由网景公司倡导,后来由IETF来主导,IETF以SSL为基础开发了TLS。
密钥加密算法
以下算法都是密钥的生成算法:
DES:数据加密标准
IBM公司研发,1997年被美国指定为数据加密标准。
3DES:三种DES加密
AES:高级加密标准
报文完整性鉴别
报文摘要
- 对长度固定且比整个报文长度短得多的报文摘要来进行加密,得到报文鉴别码;接收方来验证报文鉴别码是否一致。(对整个报文加密太耗时了)
报文摘要算法:
- MD5:输出128位的报文摘要。被中国学者王小云证明,可以找到两个报文,使其拥有相同的MD5报文摘要。导致其被SHA-1取代
- SHA:输出160位比特的报文摘要。(SHA-1也曾被王小云团队攻破)SHA-1仍在使用,但会逐渐被SHA-2和SHA-3取代
数字签名
证明报文的真实来源。保证如下三点:
- 接收方能够核实发送方对报文的数字签名
- 任何人都无法伪造签名
- 发送方事后不能抵赖对报文的数字签名
有多种实现数字签名的方法,采用公钥 - 私钥对的方法比较容易实现:
- A用自己的私钥加密报文,发送给B;B用成对的公钥来解密得到报文。
混合加密机制
对称加密 + 非对称加密
- 在交换秘钥阶段,采用非对称加密。
- 在通信阶段,采用对称加密。
非对称加密开始时,如何证明服务端发过来的公钥就是合法的?
证书
CA机构颁发公钥证书来证明公钥合法性。
- 服务端向CA机构提出公开秘钥的申请
- CA机构向对公钥做数字签名,把已签名的公钥放到公钥证书里面绑定到一起。
- 服务器就会把公钥证书发送给客户端。
- 客户端接收到证书,会用CA机构的公开密钥来验证签名。验证通过后就可证明:1. CA机构的证书真实有效,2. 服务端的公钥有效。
CA 公钥
大部分CA机构的公开密钥已经被提前植入到浏览器中。
自签名证书
使用OpenSSL开源程序,每个人都可以构建自己的认证体系,给自己颁发服务器证书。这被称为自签名证书。
实体鉴别
通信双方验证另一方身份的技术。
- 直接传输用户名和密码,用对称加密。这样有缺陷:中间人C可以截获从A发出来的加密的报文,传送给B;B会误认为中间人C就是发送者A,这叫Replay Attack重放攻击

-
应对重放攻击,可以采用不重数方法:A给B发送的报文包含A的用户名和一个随机数Ra,B收到后发送响应报文,其中用对称密钥加密随机数Ra,同时给出自己的随机数Rb,A收到后也给出响应报文,包含对称加密的Rb。
[!info] Challenge-Response 协议
这种使用随机数(不重数)进行实体鉴别的方法称为 Challenge - Response 协议。
SSL Handshake过程

非对称加密总结
-
公钥加密、私钥解密 - 任何有公钥的人,都能发送加密消息给持有私钥的对方;私钥签名、公钥验签 - 私钥签出来的任何东西,都能被验证合法性。
-
非对称加密用来安全的交换对称加密的秘钥,对称加密用来加密传输数据。
- 为啥不用非对称加密来加密通信数据?一是因为服务端不可能保存如此多的客户端公钥;而是非对称加密的计算开销远远大于对称加密,为服务端的性能考虑。
中间人问题
- 如果只用对称加密 - 中间人可以轻而易举的获取到公钥,这就等于没加密。
- 如果只用非对称加密 - 服务端给客户端发的消息只能用自己的私钥加密 - 中间人可以获取到公钥,解密消息。
- 如果对称加密和非对称加密同时使用,但是没有CA机构的认证过程存在的话
- 中间人一方面可以伪装成服务端给客户端发公钥,客户端信息会发给中间人被解密。
- 另一方满可以伪装成客户端,向服务端索要公钥,将解密消息后的消息用服务端公钥加密发给服务端。
- 等于是消息被窃听了。
所以HTTPS = 对称加密 + 非对称加密 + CA + HASH(加密算法)
性能分析
- HTTPS要比HTTP慢2-100倍
- 通信慢:SSL连接增大了通信量。
- 处理慢:client和server端都要进行加解密,消耗硬件资源。
确认用户身份的认证
某些web可能只让特定的人来浏览,需要让访问的客户端自报家门,需要去验证一些只有用户本人才有的信息。常用的认证种类有:
- 密码
- 动态令牌
- 生物认证
- IC卡等
HTTP 1.1的认证方式
- BASIC认证:基本认证
- DIGEST认证:摘要认证
以上两种是HTTP自带的认证方式。
- SSL客户端认证
- FormBASE认证:基于表单的认证
- Windows统一认证:Keberos认证、NTLM认证等。
BASIC认证
认证步骤
- 当请求的资源需要BASIC认证时,服务器返回401 Authentication Required,返回带首部字段WWW-Authenticate,包含认证方式BASIC,和Request-URI安全域字符串(realm)。Realm是为了辨别请求URI所指定的资源受到的保护策略。
- 客户端输入用户名密码,用:连接,经BASE64编码发送给服务端,服务端验证。
BASIC认证密码不经加密,不安全;除此之外如果想再进行一次认证,一般浏览器无法进行认证的注销。所以并不被常用。
Digest认证
- HTTP1.1开始有,同样采用challenge/response模式,但是不会明文发送用户名密码。
- 大致过程是客户端请求资源 - 服务端返回401+质询码 - 客户端算出响应码返回。
认证步骤

- 客户端请求需要认证的资源,服务端返回401 Authorization Required,在WWW-Authenticate首部字段中必须包含:
- 质询码,nonce,是一个随机数
-
realm:限定需要认证的资源范围。
-
客户端返回的首部字段Authorization中,必须包含:
- username:是realm限定的范围中,进行认证的用户名。
- realm
- nonce
- uri:digest-rui,就是request-uri的值,考虑到request-uri的值可能会被代理改变,提前复制一份在这里。
- response:就是返回的响应值,也叫Request-Digest;一般是经过MD5运算的密码字符串。
Digest 认证局限性
Digest可以避免密码暴露,但是不能防止用户伪装;所以使用仍不广泛。
SSL客户端认证
- 借助HTTPS,凭借客户端证书来确认客户端。
- SSL客户端认证会与表单认证一起验证客户端真实性和用户真实性。
基于表单的认证
- BASIC和DIGEST是HTTP带着的,但是几乎没人用;SSL客户端认证,要花钱,导入客户端也有门槛,应用也不广泛。所以现在都是web程序自己实现基于表单的认证。
Session、Cookie
-
基于表单认证登录信息以及认证过程,都没有标准化方法;服务端如何保存用户提交的登录信息,也没有标准化方法。
-
一般会使用cookie来管理session:
-
客户端把登录信息(用户名密码等)以POST请求发给服务器。
- 服务端发放SessionID,来唯一标识用户;把用户的登录状态绑定SessionID,保存在服务端。
- 服务端向客户端返回时,首部字段Set-Cookie里面写入SessionID。
- 客户端下次发送请求带着包含SessionID的Cookie,服务端就能识别出用户和登录状态。
构建Web内容的技术
HTML
- web页面几乎都是HTML写的。
- 采用标签来描述网页结构和内容。
CSS
- 从审美角度描述网页样式,指定HTML各种元素如何展示;让文档内容和设计分离。
DOM
- document object model,是一套用于操作HTML和XML文档的API。用于构建动态HTML。
- DOM可以将HTML的元素当做对象来操作,比如取出元素内的字符串,改变CSS属性等
JavaScript
- 脚本语言,跟Java没关系,用来控制网页行为。
用HTML、CSS、js编写WWW Web文档,由浏览器负责解析和渲染。
Web应用
- 客户端发送请求时,返回事先编好的HTML,就叫做静态内容
- 客户端请求后,返回由Web服务器上的程序生成的内容,叫做动态内容。
CGI
- common gateway interface,通用网关接口。
- Web服务器接收到请求后,转发给程序的一组机制;CGI程序会对请求内容做出相应的动作,比如创建HTML等。
Servlet
CGI每次接到请求都要启动一次,会增加高并发下的负载,成为性能瓶颈;
- Servlet是可以在服务器上创建动态内容的程序,与web服务器运行在相同的进程中,比较轻量。Servlet的运行环境称为Web容器
- Servlet是Java实现的一套接口,
数据发布的格式和语言
XML
- 用标签分隔的树形结构,通过语法分析器的解析功能来解析XML并取出元素,可以方便数据在程序间的共享。
JSON
- 以JavaScript对象表示法为基础的数据标记语言