HTTP补充之URL核心结构
大多数URL 方案的URL 语法都建立在这九部分的通用格式上,
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
当然最重要的是三个部分 方案(scheme)主机(host)路径(path)
常用的协议
file
表示一台主机(通过本地磁盘,网络文件或者其他一些共享文件上可以直接访问的文件)
http
长文本传输协议,除了没有用户名和密码之外,与通常的URL格式相符,默认80端口
https
方案https与方案http是一对,唯一区别在于使用了网景的SSL,SSL为HTTP连接提供了端对端的加密机制,语法和http一致,默认端口443
ftp
文件传输协议 URL可以用来从FTP服务器上下载文件,并获取FTP服务器上的文件结构内容列表,在Web和URL之前就出现了FTP
HTTP报文
HTTP 报文是在HTTP应用程序之间发送的数据块。这些数据快以一些文本形式的元信息(meta-information)开头,这些信息描述了报文的内容以含义,后面跟着可选数据部分。这些报文在客户端,服务器和代理之间流动。
术语入流 上游以及下游都是用来描述报文方向的
HTTP 使用术语流入和流出用来描述事务处理的方向,报文流入源端服务器,工作完成之后,会流入用户的Agent代理中
HTTP报文像河水一样流动。不管是请求报文还是响应报文,所有报文都会向下流动。所有报文的发送者都是接收者的上游
报文格式详解
所有报文都可以分为两类:请求报文(request message)和 响应报文(response message)
请求方法
最常用的就是GET和POST方法了,这两个方法从HTTP的报文格式上就可以知道,一个是携带的主体数据,另一个知识考请求的参数进行传递数据
**GET **是最常用的方法,通常用于请求服务器的某个资源
HEAD 方法与GET 类似,只是服务器在响应中只返回首部,不会返回主体资源。这就允许客户端在为获取实际资源的情况下,对资源的首部进行检查
- 使用HEAD ,可以在不获取资源的前提下,了解资源的情况信息
- 查询资源是否存在
PUT 与 GET 重服务器读取资源相反,PUT 方法会向服务器写入文档
POST 方法起初是用来想服务器输入数据的(提交表单)
POST 用于向服务器发送数据。PUT 用于向服务器上的资源(例如文件)中存储数据
状态码
可以通过三位数字代码对不同状态码进行分类。
- 200 到299 之间的状态码表示成功。
- 300 到399 之间的代码表示资源已经被移走了。
- 400 到499 之间的代码表示客户端的请求出错了。
- 500 到599 之间的代码表示服务器出错了。
HTTP 本身就支持一种简单的机制,可以对请求进行质询/ 响应认证。这种机制要求客户端在获取特定的资源之前,先对自身进行认证(token),这样就可以使事务稍微安全一些。
TCP 连接详解
HTTP 要传送一条报文时,会议流的形式将报文数据的内容通过一条TCP连接按序传输。TCP收到数据流之后,会将数据流砍成被称为段的小数据块并将段封装到IP分组中,通过因特网进行传输,(分包传输)
一个数据包中并不完全全是数据包,包含了一下头信息,检验信息等,实际一个包在1400一下,甚至更低
一个报文会拆分多个包传输,发送的时候如何保证顺序呢,TCP是顺序传输,发送的时候TCP协议为每一个包编号,以便接受的以访方便还原,即使丢包也知道丢的是哪一个。
TCP连接的性能分析
HTTP事务的时延
串行HTTP的事务的时间线(服务器的处理时间其实很短暂)
HTTP 事务的时延有一下几个因素
- 客户端需要根据域名来分析IP和端口号,这个DNS查询需要时间
- 接下来,客户端回想服务器发送一条TCP连接请求,并等待服务器回送一个请求接受答应。每一条新的TCP连接都会有建立时延,这个值通常最多只有一二十毫秒,但是如果请求数量一多,这个就立马叠上去了
- 一旦连接建立起来了,客户端就是通过新建立的TCP管道来发送HTTP协议,数据到达时,web服务器从TCP连接中取得请求报文,并进行处理,这些对需要处理时间
- 最后再会送HTTP响应。这些TCP网络时延通常大小取决于硬件速度,网络,带宽,服务器负载以及报文大小等
TCP连接的延迟和延迟确认
由于因特网自身无法确保可靠的分组传输(因特网路由器超负载的话,可以随意丢弃分组)所以TCP实现了自身的确认机制来确保成功传输(一个包里面都有包的编码,校验信息等)每个TCP 段都有一个序列号和数据完整性校验和。每个段的接收者收到完好的段时,都会向发送者回送小的确认分组。如果发送者没有在指定的窗口时间内收到确认信息,发送者就认为分组已被破坏或损毁,并重发数据。为了保证减少不必要的检查和错误的检测结果,TCP会使用一个延迟确认算法, 会将一个确认信息在一个窗口时间(一般是100~200ms)外再进行发送
HTTP事务的慢启动
TCP数据传输的性能还取决于TCP连接的使用期。TCP会随着时间的进行会进行自我调节,起初会限制传输的速度,随着成功传输的时候推移提高速度。为防止因特网的突然过载太大,导致服务器挂了
TCP连接的串行事务处理时延
如果只对连接进行简单的管理,TCP的性能时延会叠加
比如,假设有一包含了三个嵌入图片的web界面,浏览器需要发起四个HTTP事务来显示这个界面,1一个用于请求主界面,另外三个用来请求图片,如果每一个事务都需要建立(串行的建立)一个新的连接,那么连接时延和慢启动就会叠加起来
TCP连接值并行连接
HTTP允许客户端打开多条连接,并执行多个HTTP事务
包含嵌入对象的组合界面(iframe或者是多个外联文件等)如果能(通过并行连接)克服单条连接的空载时间和带宽限制,加载速度也会有所提高,。时延可以重叠起来,而且如果单条连接没用充分利用客户端的因特网带宽,可以将未用的带宽分配来装载其他对象
并行连接不一定更快,但一般看上去会感觉更快 举一个最简单的例子,打开游戏的时候都有一段动画,其实就是为了遮掩游戏在加载,不会造成卡机假象
TCP连接的持久连接
web 客户端经常会打开到同一个站点,比如一个web界面上大部分内嵌的图片通常来自于同一个站点,而且相当于一部分指向其他对象的超链接都通常指向一个站点。因此,初始化对某个服务器HTTP请求的应用程序很可能会在不久的将来在对那台服务器发起更多的请求(获取在线图片)这种性质的站点被称为站点局部性
因此,HTTP/1.1以上版本 允许HTTP设备在事务处理结束之后将TCP连接状态打开,一边未来的HTTP请求重用现存的连接。在事务处理结束之后依然保持在打开状态的TCP连接被称为持久连接。重用已对目标服务器打开的空闲持久连接,就可以避开缓慢的连接建立改成,而且打开的连接还可以避免慢启动的拥塞适应阶段,以便快速传输。
TCP连接的持久连接和并行连接的缺点
并行连接可以提高复合界面的传输速度,但并行连接也有一些缺点
- 每一个事务都会打开 / 关闭一条新的连接 会损耗时间和带宽
- 由于TCP慢启动的特性存在,每一条新连接的性能都会有所减低
- 可打开的并行连接数量实际上是有限的
持久连接有一些比并行连接更好的地方,持久连接降低了时延和连接建立的开销,将连接状态保持在连接状态,而且减少了打开连接的潜在数量,但是,管理持久连接时要特别小心,不会就会积累大量的空闲连接,损耗本地已经服务器的资源
持久连接和并行连接配合使用可能时最高效的方式,现在很多web应用程序都会打开小量的并行连接,其中每一个但是持久连接
持久连接的实现方式
持久连接有两种类型
- 比较老的HTTP1.0+ 的 ”keep-alive“
- 现代的HTTP/1.1 “persistent”
实现HTTP/1.0 keep-alive 连接的客户端可以通过包含Connection: Keep-Alive首部请求将一条连接保持在打开状态
HTTP/1.1 逐渐停止了keep-alive 连接的支持,用一种名为持久连接(persistent-connection)的改进型设计取代了它。持久连接的目的与keep-alive 连接的目的相同,但工作机制更优一些。
与HTTP/1.0+ 的keep-alive 连接不同,HTTP/1.1 持久连接在默认情况下是激活. 除非特别指明,否则HTTP/1.1 假定所有连接都是持久的。要在事务处理结束之后将连接关闭,HTTP/1.1 应用程序必须向报文中显式地添加一个Connection:close 首部。
这是与以前的HTTP 协议版本很重要的区别,在以前的版本中,keepalive连接要么是可选的,要么根本就不支持。
TCP连接的管道连接
管道话连接:在响应到达之前,可以将多个请求放入队列。当地一条请求通过网络刘翔服务器时,第二条之后的请求都可以开始发送了,在高延迟的网络条件下,这样做可以降低网络的环回时间提高性能
局限性:
- 如果 HTTP 客户端无法确认连接是持久的,就不应该使用管道
- 必须按照与请求相同的顺序回送 HTTP 响应。HTTP 报文中没有序列号标签,因此如果收到的响应失序了,就没办法将其与请求匹配起来了
- HTTP 客户端必须做好连接会在任意时刻关闭的准备,还要准备好重发所有未完成的管道化请求。如果客户端打开了一条持久连接,并立即发出了10 条请求,服务器可能在只处理了5 条请求之后关闭连接。剩下的5 条请求会失败,客户端必须能够应对这些过早关闭连接的情况,重新发出这些请求。
- HTTP 客户端不应该用管道化的方式发送会产生副作用的请求(比如 POST)。总之,出错的时候,管道化方式会阻碍客户端了解服务器执行的是一系列管道化请求中的哪一些。由于无法安全地重试POST 这样的非幂等请求,所以出错时,就存在某些方法永远不会被执行的风险。
TCP连接的关闭
TCP 连接时双向的。TCP连接的每一端都有一个输入队列和输出队列,用于数据的读写,放入一端的输出队列的数据始终会出现在另一端的输入队列中
关闭连接的输出信道总是很安全的,关闭连接的输入信道比较危险,除非你知道另一端不打算再发送其他数据了
服务器的概念
实际的服务器会做什么?
- 建立连接 --- 接受一个客户端连接
- 接受请求--- 从网络中读取一条HTTP 请求报文
- 处理请求 --- 对请求报文进行解释,并采取行动
- 访问资源 --- 访问报文中指定的资源
- 构建响应 --- 创建带有正确首部的HTTP 响应报文
- 发送响应 --- 将响应会送给客户端
- 记录事务处理过程 --- 将以完成事务有关的的内容记录在日志文件中
Web 代理(proxy)服务器时网络的中间实体。代理位于客户端和服务器之间,扮演中间人的角色在各端点之间来回传HTTP报文
反向代理:假扮Web 服务器被称为替代物(surrogate)或反向代理(reverse proxy)的代理接收发给Web 服务器的真实请求,但与Web 服务器不同的是,它们可以发起与其他服务器的通信,以便按需定位所请求的内容。
服务器缓存的概念
有很多客户端访问一个流行的原始服务器页面时,服务器会多次传输同一份文档,每次传送给一个客户端。一些相同的字节会在网络中一遍遍地传输。这些冗余的数据传输会耗尽昂贵的网络带宽,降低传输速度,加重Web 服务器的负载。有了缓存,就可以保留第一条服务器响应的副本,后继请求就可以由缓存的副本来应对了,这样可以减少那些流入/ 流出原始服务器的、被浪费掉了的重复流量。
缓存解决常见问题
- 宽带瓶颈
- 瞬间拥塞
- 距离时延(服务器距离)
可以用已用副本为某些达到缓存的请求提供服务。这些被称为缓存命中(cache hit)其他一些达到缓存的请求可能会由于没有副本可用,而被转发到原始服务器,这被称为缓存未命中 (cache miss)
客户端识别
为什么要进行客户端识别,以淘宝为例
- 个性化的问候
- 管理信息存档
- 记录会话
可以实现客户端识别的方式有很多,
- 承载用户身份信息的HTTP首部
- 客户端IP地址追踪,通过用户的IP地址对其进行识别
- 用户登陆,用认证方式来识别用户(配置首部的Authorization)
- cookie
cookie
可以笼统地将cookie 分为两类: 会话cookie 和持久cookie。会话cookie 是一种临时cookie,它记录了用户访问站点时的设置和偏好。用户退出浏览器时,会话cookie 就被删除了。持久cookie 的生存时间更长一些;它们存储在硬盘上,浏览器退出,计算机重启时它们仍然存在。通常会用持久cookie 维护某个用户会周期性访问的站点的配置文件或登录名。
会话cookie 和持久cookie 之间唯一的区别就是它们的过期时间。
服务器认证
服务器认证的缺陷
基本认证简单便捷,但并不安全。只能用它来防止非恶意用户无意间进行的访问,或将其与SSL 这样的加密技术配合使用。
(1) 基本认证会通过网络发送用户名和密码,这些用户名和密码都是以一种很容易解码的形式表示的。如果有动机的第三方用户有可能会去拦截基本认证发送的用户名和密码,就要通过SSL 加密信道发送所有的HTTP 事务,或者使用更安全的认证协议,比如摘要认证。 (2) 即使密码是以更难解码的方式加密的,第三方用户仍然可以捕获被修改过的用户名和密码,并将修改过的用户名和密码一次一次地重放给原始服务器,以获得对服务器的访问权。没有什么措施可用来防止这些重放攻击。 (3) 即使将基本认证用于一些不太重要的应用程序,比如公司内部网络的访问控制或个性化内容的访问,一些不良习惯也会让它变得很危险。很多用户由于受不了大量密码保护的服务,会在这些服务间使用相同的用户名和密码。比如说从免费的因特网邮件网站捕获明文形式的用户名和密码,然后会发现用同样的用户名和密码还可以访问重要的在线银行网站! (4)假冒服务器进行欺骗, 以得到用户发送的账号和密码,并存储起来以供后期使用
摘要认证遵循的箴言是“绝不通过网络发送密码”。客户端不会发送密码,而是会发送一个“指纹”或密码的“摘要”,这是密码的不可逆扰码。客户端和服务器都知道这个密码,因此服务器可以验证所提供的摘要是否与密码相匹配
摘要是一种单向函数,主要用于将无线的输入转换为一个有限的浓缩输出值,最常见的就时MD5(MD5会将任意长度的字节序列转换为一个128位的摘要)
HTTPS的基本概念
我们需要一种能够提供一下功能的HTTP安全技术
- 服务器认证(客户端知道它是在跟真正的服务器通信而不是伪造的)
- 客户端认证(服务器要知道它们是在跟真正的客户端通信而不是伪造的)
- 完整性(客户端和服务器的数据不会被修改)
- 加密(客户端和服务器对话时私密的,无需担心被担心被窃听)
- 效率(一个足够快的算法,满足低端用户)
- 普适性(基本上所有客户端和服务器都支持)
- 管理的可扩展性(在任何地方任何人都可以立即进行安全通信)
几个概念
密码:对文本进行编码,使得偷窥者无法识别的算法
密钥:改变密码行为的明文参数
对称密钥加密系统:编码和解码使用相同的密钥的算法
不对称密钥加密系统:编码和解码使用不同的密钥算法
公开密钥加密系统:一种能够使百万计算机便捷的放送机密报文的系统
数字签名:用来验证报文未被伪造或者篡改的校验
数字证书:用一个可信的组织验证和签发的识别信息
对称机密技术
编码 / 解码使用相同密钥的算法,对称算法加密技术的缺点就是发送者和接收者相互对话之前,一定要有一个共享的保密密钥
在对称密钥加密技术中,发送端和接收端要共享相同的密钥才能进行通信。发送端用来共享的密钥来加密报文,并将得到加密的报文发送给服务端。服务器再根据相同的共享密钥回复原始的明文
可用密钥值的数量取决于密钥中的位数,以及可能的密钥中有多少是有效的。就对称密钥加密技术来说,通常所有的密钥值都是有效的。8 位的密钥只有256 个可能的密钥值, 40 位的密钥可以有2^40 个可能的密钥值(大约是一万亿个密钥),128 位的密钥可以产生大约340 000 000 000 000 000 000 000 000 000 000 000 000 个可能的密钥值。现在一般采用的都是128位的加密
公开密钥加密技术
公开密钥加密技术没有为每对主机使用单独的加密/ 解密密钥,而是使用了两个非对称密钥:一个用来对主机报文编码,另一个用来对主机报文解码。编码密钥是众所周知的(这也是公开密钥加密这个名字的由来),但只有主机才知道私有的解密密钥
数字签名
数字签名是附加在报文上的特殊加密校验码。使用数字签名有以下两个好处。
- 签名可以证明是作者编写了这 条报文。只有作者才会有最机密的私有密钥, 因此,只有作者才能计算出这些校验和。校验和就像来自作者的个人“签名”一样。
- 签名可以防止报文被篡改。如果有恶意攻击者在报文传输过程中对其进行了修改,校验和就不再匹配了。由于校验和只有作者保密的私有密钥才能产生,所以攻击者无法为篡改了的报文伪造出正确的校验码。
数字证书
数字证书中还包含一组信息,所有这些信息都是由一个官方的“证书颁发机构”以数字方式签发的。基本的数字证书中通常包含一些纸质ID 中常见的内容,比如: • 对象的名称(人、服务器、组织等); • 过期时间; • 证书发布者(由谁为证书担保); • 来自证书发布者的数字签名;
而且,数字证书通常还包括对象的公开密钥,以及对象和所用签名算法的描述性信息。任何人都可以创建一个数字证书,但并不是所有人都能够获得受人尊敬的签发权,从而为证书信息担保,并用其私有密钥签发证书
通过HTTPS 建立了一个安全Web 事务之后,现代的浏览器都会自动获取所连接服务器的数字证书。如果服务器没有证书,安全连接就会失败。服务器证书中包含很多字段,其中包括:
• Web 站点的名称和主机名; • Web 站点的公开密钥; • 签名颁发机构的名称; • 来自签名颁发机构的签名。
在发送已加密的HTTP 报文之前,客户端和服务器要进行一次SSL 握手,在这个握手过程中,它们要完成以下工作:
• 交换协议版本号; • 选择一个两端都了解的密码; • 对两端的身份进行认证; • 生成临时的会话密钥,以便加密信道。