网络基础

1.网络传输的知识

1. 网络传输的知识

超文本传输协议(HTTP)是一种分布式、合作式超媒体信息系统。它是一种通用的、无状态的协议,除了应用于超文本传输外,它也应用于诸如名称服务器和分布对象管理系统之类的系统,这可以通过扩展它的请求方法、错误代码和报头来实现。HTTP的一个特点是数据表现形式是可输入的和可协商性的,这就允许系统能被建立而独立于数据传输。

1.1 协议

比如在外卖送餐中甲方和乙方协商后的各种约定,就称为协议。(酒店A收到公司发送的订餐申请单时会根据申请单协议的内容为公司提供订餐服务,向公司提供订餐申请中的加班餐食物等。)信息通过协议准确无误地传达申请人与服务方间互相需要表达的意思,用以清晰地得到各自所需的服务及数据。这就是协议的作用。每个协议可能需要获取不同的信息,即格式及传输的数据内容不同。 一般网络传输协议可以分为 HTTP协议、HTTPS 协议、以及WebSocket协议等。

1.2 Cache

(当我们在饥肠辘辘地等待外卖时,最关注的问题是什么?当然是配送时间。这个时间关系到两部分的质量。 1.订餐者自身的感受:配送慢,则员工焦虑饥饿,导致无法集中精神工作;配送快,则员工情绪佳,省时,提高工作效率; 2.饭菜的质量:配送慢,饭菜已经凉了,已经没有原先的美味;配送快,饭菜还是热乎乎的,不影响口感品质。)从技术的角度来说,我们把用户的等待时间称为响应时间,也就是开发人员所说的性能。会有多方面的指标帮助测试及开发人员判定性能的好坏,其中最直观的就是看网页及应用的打开速度。其中提高反应速度的一个方式就是使用缓存。一个优秀的缓存策略可以为网络传输带来以下两方面好处。
(1)减少延迟:因为所发出的网页请求是指向更接近客户端的缓存,而不再是源服务器端,因此请求所花费的时间更短,这让网站看上去反应更快,提高了用户体验。

(2)降低网络负荷: 因为缓存文件可以重复使用,节省不少的带宽,降低了网络负荷。同时站在用户的角度,这也节省了不少流量。
从以上例子可以得出缓存的概念: 使用缓存 Cache 的站点会监听客户端向服务器端发出的请求,并根据相应的缓存设置保存服务器端反馈的数据,比如 HTML 页面、图片等文件。如果用户再次使用相同 URL 发送请求,请求不会直接发向服务器,而是通过缓存策略先行判断是否能够使用之前已经保存下来的反馈文件,从而降低服务器的负载及提高数据的响应时间。

缓存根据其类型可分为以下几种:

  1. 浏览器缓存
    它可以将你浏览过的网页全部保存到你本地计算机的硬盘中。最常用的场景就是当你点击浏览器的 ''后退‘‘ 或者曾经浏览过的页面的链接时就能直接使用这种缓存。

  2. 代理缓存
    开发者需要存储大规模的数据及面向更广泛的用户群时,可以使用代理缓存。因为代理缓存既不属于客户端,也不属于服务器端,而是利用网络路由请求信息。有以下两种最常用的场景。
    (1)用户手动设置浏览器的代理。
    (2)使用网页代理,网页代理将你的 URL 请求通过它潜在的网络定向到代理,所以用户甚至无需手动配置它们。代理缓存是共享缓存的一种,不是只有一个人正在使用它们,而是同时存在大量的用户使用。

  3. 网关缓存
    从作用上来说,它同样起到了代理缓存的用处。从协议的角度来说,网关缓存在受用领域上与代理缓存有区别。
    (举个例子,代理缓存就像是‘‘外卖平台” 中的配餐服务,而网关缓存就是"外卖平台"中的配送服务。配餐服务可以使用订餐协议,而配送服务就需要使用与配餐不同的配送协议了。) 网关可以为通信线路上的服务器提供不同的协议服务。

在缓存的概念中,还有一项比较重要的内容,就是按缓存策略来分,缓存分为以下两种情况:
(1) 强缓存
缓存策略:直接从本地缓存中取资源,不会和服务器通信。
(2) 协商缓存
缓存策略:通过服务器来告知是否能用本地缓存。先和服务器通信,如果返回可以使用本地缓存的指示,再从本地缓存中取;如果不可以使用本地缓存,就会返回最新的资源。

1.3 Cookie

协议有很多种,订餐协议就是一种无状态协议。(酒店 A 从当前数据传输上无法知道订餐者身份。怎么办?就给订餐的公司颁发一个通行证吧,每个公司一个,无论谁需要订餐,都必须携带自己的通行证。这样酒店 A 就能从通行证上确认订餐者身份了。)

Cookie 的内容是保存的一小段文本信息,这些文本信息组成一份通行证。它是客户端对于无状态协议的一种解决方案。
Cookie 的使用原理如下:
(1)用户会提供包括用户名在内的订餐信息并且将其提交至服务器。
(2) 服务器向客户端回传相应数据的同时,也会发回这些订餐信息 Cookie S-001。
(3) 当客户端接收到来自服务器的响应之后,浏览器会将 Cookie S-001 存放在一个统一的位置。
(4) 客户端再向服务器发送请求的时候,会把 Cookie S-001 再次发回至服务器。

既然协议的无状态性可以通过使用 Cookie 技术来解决,那么浏览器会在本地保存 Cookie 信息。对于测试人员来说,如果要模拟有状态的请求行为,就可以通过直接向服务器提交已保存的 Cookie 信息以便绕过身份认证,优化测试步骤。要利用 Cookie 作为测试的手段。

获取 Cookie 的途径:
a. 使用浏览器的开发者工具或专业抓包工具获取
b. 从本地文件中获取
c. 通过前端技术获取
测试人员可以通过前端技术查看某个网站颁发的 Cookie。例如,在浏览器地址栏中输入: Javascript:alert(document, cookie) 就可以查看到 Cookie 信息。

Cookie 的生命周期:
一般大家都会认为浏览器关闭时就会自动清除 Cookie 。其实这个说法不正确, Cookie 的生命周期是可以设置的,所以当你在创建测试场景的时候,可以根据需求进行相应的设置。
Cookie 的生存时间是整个会话期间:浏览器会将 Cookie 保存在内存中,浏览器关闭时就会自动清除这个 Cookie。

Cookie 的生命时间是长久有效:Cookie 保存在客户端的硬盘中,浏览器关闭的话,该 Cookie也不会被清除,下次打开浏览器访问对应网站时,这个 Cookie 就会自动再次发送到服务器端。
测试人员可以通过对浏览器的设置修改Cookie的生命周期。

Cookie 不可跨域名以及跨浏览器使用:
一般 Cookie 是不可跨域名的,这是由 Cookie 的隐私安全机制决定的。隐私安全机制能够禁止网站非法获取其他网站的 Cookie。除了不能跨域名使用,它也不能跨浏览器使用。 (大家可能会遇到一种情况,既然 Cookie 不能在不同的浏览器中使用,为什么使用 IE 登录了腾讯网站后,使用 Firefox 能保持登录状态呢? 不同浏览器使用不同的 Cookie 管理机制,无法实现公用的 Cookie 。如果使用 IE 登录腾讯网站,使用 Firefox 也能登录,这是由于在安装腾讯 QQ软件时,你的计算机上同时安装了针对这两个浏览器的插件,可以识别本地已登录 QQ号码进而自动登录。本质上,这个现象并不是由 Cookie 造成的。)

1.4 Session

那么问题来了,如果公司丢失了通行证怎么办?(酒店 A 难道就不保留公司信息吗? 酒店 A 会创建公司的 “订餐明细表” 用于保存及确认公司的身份。如果说 Cookie 机制是通过检查公司身上的 “通行证” 来确定公司身份的话,那么 Session 机制就是通过检查酒店 A 的 “公司订餐明细表” 来确认公司身份,当公司需要订餐时只需要查询订餐明细表就可以为相应公司提供配餐服务了。)
同样为解决订餐协议的无状态性, Session 是另一种记录用户状态的机制,不同的是Cookie 保存在客户端浏览器中,而 Session 保存在服务器上。它是服务器端对于无状态协议的一种解决方案。 客户端访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是 Session。客户端再次访问时只需要从该 Session 中查找该用户的状态即可。

Session 的传输步骤如下:
(1)服务器端程序运行的过程中创建 Session ,并且为该 Session 生成唯一的 Session ID.这个 Session ID在随后的请求中会被用来重新获得已经创建的 Session。在 Session 被创建之后,就可以调用 Session 相关的方法向 Session 中增加内容,这些内容只会保存在服务器中。
(2)服务器将 Session ID 发送到客户端。
(3)当客户端再次发送请求的时候,会将这个 Session ID 带上.
(4)服务器接收到请求之后就会依据 Session ID 找到相应的 Session,完成请求响应。

Session 的传输媒介:

  1. 通过 Cookie 传输
  2. URL 地址重写
    URL 地址重新是对客户端不支持 Cookie 的解决方案。它的原理是将该用户 Session 的 ID 信息重写到 URL 地址中。服务器能够解析重写后的 URL,获取 Session 的 ID。这样即使客户端不支持 Cookie ,也可以使用 Session 来记录用户状态。
    服务器代码会先自动判断客户端是否支持 Cookie 。如果客户端支持 Cookie ,会将 URL原封不动地输出。如果客户端不支持 Cookie ,则会将用户 Session 的 ID 重写到 URL 中。
    如果测试人员要构造特殊测试场景,需要获取非 Cookie 传输的 Session ,方法是要找开发人员帮忙获取 Session ID 或者自行从服务器端代码中获取。

Session的生命周期:
对于 Session 来说也是一样的,除非程序通知服务器删除一个 Session,否则服务器会一直保留,程序一般都是在用户做 log off 的时候发个指令去删除 Session 。
关闭浏览器不会导致 Session 被删除,迫使服务器为 Session 设置了一个失效时间,当距离客户端上一次使用 Session 的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把 Session 删除,以节省存储空间。例如, Tomcat 中 Session 的默认超时时间为 20分钟。

Session 与 Cookie 的区别:
1.存储位置不同
通常情况: Cookie 的数据信息存放在客户端浏览器上。 Session 的数据信息存放在服务器上。

  1. 存储容量不同
    通常情况:单个 Cookie 保存的数据 <= 4KB,一个站点最多保存 20个 Cookie. 对于 Session 并没有上限,但由于对服务器端的性能考虑,Session内不要存放过多的东西,并且设置 Session 删除机制。

  2. 存取方式不同
    Cookie 中只能保管 ASCII 字符串,需要通过编码的方式存放 Unicode 字符或者二进制数据。运用 Cookie 难以实现存储略微复杂的信息。
    Session中能够存取任何类型的数据,包括且不限于 String、Integer、List、Map等。

  3. 隐私策略的不同
    Cookie 对客户端是可见的,别有用心的人可以分析存放在本地的 Cookie 并进行 Cookie 欺骗,所以它是不安全的。
    Session 存储在服务器上,对客户端是透明的,不存在敏感信息泄露的风险。
    假如选用 Cookie ,比较好的方法是:敏感的信息,如账号密码等,尽量不要写到 Cookie 中,可以将 Cookie 信息加密,提交到服务器后再进行解密。存储在本地的 Cookie 就需要自行加密了。

  4. 有效期上的不同
    在介绍 Cookie 的章节中提到,开发可以通过设置 Cookie 的属性,达到使 Cookie 长期有效。
    由于 Session 依赖于名为 JSESSIONID 的 Cookie,而 Cookie JSESSIONID 的过期时间默认为-1,只需关闭窗口该 Session 就会失效,因而 Session 不能达到长期有效的效果。就算不依赖 Cookie ,运用 URL 地址重写也不能完成,因为假如设置 Session 的超时时间过长,服务器累计的 Session 就会越多,越容易导致内存溢出。

6.服务器压力的不同
Session 是保管在服务端的,每个用户都会产生一个 Session 。假如并发访问的用户非常多,会产生非常多的 Session ,耗费大量的内存。
Cookie 保管在客户端,不占用服务器资源。对于并发用户非常多的网站,Cookie 是很好的选择。

  1. 浏览器支持的不同
    假如客户端浏览器不支持 Cookie。
    Cookie 是需要客户端浏览器支持的。假如客户端禁用了 Cookie ,或者不支持 Cookie ,则会话跟踪会失效。关于 WAP上颚应用,常规的 Cookie 就派不上用场了。
    运用 Session 需要使用 URL 地址重写方式。一切用到 Session 程序的 URL 都要进行 URL 地址重写,否则 Session 会话跟踪还会失效。关于 WAP 应用来说,Session + URL 地址重写或许是它唯一的选择。
    假如客户端支持 Cookie
    Cookie 既能够设为本浏览器窗口以及子窗口内有效(把过期时间设为 -1),也能够设为一切窗口内有效(把过期时间设为某个大于 0 的整数)
    Session 只能在本窗口以及其子窗口内有效。假如两个浏览器窗口互不相干,它们将运用两个不同的 Session (IE8 下不同窗口 Session 互不相干)

  2. 跨域支持上的不同
    Cookie 支持跨域域名访问,例如,将 domain 属性设置为 “.biaodianfu.com”,则以“.biaodianfu.com”为后缀的一切域名均能够访问该 Cookie 。跨域名 Cookie 如今被普遍用在网络中,例如,Google、Baidu、sina等。
    Session 则不会支持跨域名访问。Session 仅在它所在的域名内有效。

1.5 Token

某某以上问题都是由于服务器端需要保存 Session 信息造成的,如果服务器不用保存 Session 信息就好了。考虑至此,设计人员想出了一种以时间换取空间的方式。给所有用户发送一个令牌(Token),其是签名后的用户身份信息,每一次用户需要发送订餐请求把用户信息和这个令牌给酒店系统进行验证即可。酒店系统不保存令牌,只保留用户签名过程中的加密算法及秘钥即可。

Token 的原理:
(1) 当客户第一次请求时,发送用户信息至服务器。服务器对用户信息使用 hs256 算法及密钥进行签名,再将这个签名和数据一起作为 Token ,返回给客户端。
(2) 服务端不保存 Token ,客户端保存 Token。
(3) 当客户端再次发送请求时,在请求信息中将 Token 一起发送给 服务器。
(4) 服务器用同样的 hs256 算法和同样的秘钥,对数据再计算一次签名,和 Token 中的签名做比较。
如果相同,服务器就知道客户端已经登录过了,并且可以直接取到客户端的 user ID.
如果不相同,数据部分肯定被人篡改过,服务器就返回客户端,认证不通过。

运用 Token 服务器不再需要保存 Session ID,只负责生成 Token ,然后 验证 Token.这就是服务器用 CPU 计算时间换取 Session 存储空间的方式。 Token 的传递通常被放在 Cookie 中,如果客户端不支持 Cookie ,Token 也可以放置在请求头中。
Token 通常被用于一种轻巧的规范下,这种规范叫做 JSON Web Token (JWT).

1.6 JSON Web Token

(当酒店满足了用户订餐的基本功能后,为了提升用户活跃度,以及增强用户黏性,需要加入一系列的交互功能。)
JSON Web Token (JWT) 是一种开放标准,它定义了一种紧凑且安全的标准,用于将各方之间的信息传输为 JSON 对象。该信息通过数字签名进行验证。使用 HMAC 算法或使用 RSA 的公钥/私钥对 JWT 进行签名,它是 rest 接口的一种安全策略。
实际上 JWT 它就是一串字符串,由三个部分组成,头部、载荷、签名。

通过一个实例了解 JWT 机制实现认证过程。当用户第一次登录系统时。
创建 JWT 的步骤如下。
(1) 第一次登录,用户从客户端输入用户名/密码,提交后到服务器的登录处理 Action 层(Login Action)。
(2) Login Action 调用认证服务进行用户名密码认证。
(3) 如果认证通过,Login Action 层调用用户信息获取用户信息(包括完整的用户信息及对应权限信息)。
(4) 返回用户信息后,Login Action 从配置文件中获取 Token 签名生成的秘钥信息,进行 Token的生成。
(5) 在生成 Token 的过程中可以调用第三方 JWT Lib 生成签名后的 JWT数据。
(6) 完成 JWT 数据签名后,将其设置到 Cookie 对象中,并重定向到首页,完成登录过程。
经历过第一次登录,以后得每一次该客户端的请求都会经历请求认证。

所谓认证的步骤如下:
(1) 客户端(App 客户端或服务端) 通过 get 或 post 请求访问资源 (页面或调用 API)。
(2) 认证服务作为一个 Middleware HOOK 对请求进行拦截。基于 Token 的认证机制会在每一次请求中都带上完成签名的 Token 信息,这个 Token 信息可能在 Cookie 中,也可能在 HTTP 的 Authorization 头中。首先认证服务在 Cookie 中查找 Token 信息,如果没有找到,则在 Authorization head 中查找。
(3) 如果找到 Token 信息,则根据配置文件中的签名加密秘钥,调用 JWT Lib 对 Token 信息进行解密和解码。
(4) 完成解码并验证签名通过后,对 Token 中的 exp、nbf、aud 等信息进行验证。
(5) 全部通过后,根据获取的用户的角色权限信息,对请求的资源的权限进行逻辑判断。
(6) 如果权限逻辑判断通过,则通过 response 对象返回,否则返回未授权,登录失败。
JWT是目前项目中使用最多的处理请求无状态性的方式。使用 Token 很大程度上解决了 Session 的弊端,让数据在网络传输中更精确并且保障了数据在传输过程中的安全性。
例如,我们的安全性测试工程师就可以运用 XSS Attacks、Replay Attacks 以及 MITM Attacks 跨站脚本攻击等手段获取 Token 模拟正常请求发送场景,服务器是不会发现这是假请求的。

  1. HTTP协议
    “开放系统互联参考模型”,即著名的 OSI/RM 模型。它将计算机网络体系结构的通信协议划分为七层,自下而上依次为:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
    每一层都有其不同的含义及网络协议:
    (1) 物理层:以太网、调制解调器、电力线通信(PLC)、SONET/SDH、光导纤维、同轴电缆、PPTP等。
    (2) 数据链路层:Wi-Fi(IEEE 802.11)、WiMAX(IEEE 802.16)、ATM、令牌环、PPP、L2TP、PPTP等。
    (3) 网络层:IP(IPv4、IP v6)、ICMP、ICMPv6、IGMP、IS-IS、IPsec、ARP、RARP等。
    (4) 传输层:TCP、UDP、TLS、DCCP、SCTP、RSVP、OSPF等。
    (5) 会话层:
    (6) 表示层:
    (7) 应用层:DNS、FTP、Gopher、HTTP、IMAP4、POP3、SIP、SSH、TELNET、RPC、SDP、SOAP、GTP等。

2. HTTP协议

2.1 协议介绍

超文本传输协议(HTTP) 是一种分布式、协作式的,面相超媒体的传输系统。它是一种通用的、无状态的协议,除了应用于超文本传输外,它也可以应用于如名称服务器和分布对象管理系统之类的系统,这可以通过扩展它的请求方法、错误代码和信息头来实现。HTTP是建立在统一资源标识符(URI) 的约束上的,作为一个地址(URL) 或名称(URN),以指定被一个方法使用的资源。
HTTP/1.0 没有充分考虑到分层代理、缓存以及持久连接和虚拟主机的需求的影响。升级版的 HTTP/1.1 这个协议比 1.0 更为严格,以确保各个协议的特征得到可靠实现。
HTTP 术语:
连接(connection)
消息(message)
请求(request)
响应(response)
资源(resource)
实体(entity)
表现形式(representation)
内容协商(content negotiation)
变量(variant)
客户端(client)
用户代理(user agent)
服务器(server)
源服务器(Origin server)
代理(Proxy)
网关(gateway)
隧道(tunnel)
缓存(cache)
可缓存的(cacheable)
第一手的(first-hand)
显式过期时间(explicit expiration time)
启发式过期时间(heuristic wxpiration time)
年龄(age)
保鲜寿命(freshness lifetime)
保鲜(Fresh)
陈旧(Stale)
语义透明(semantically transparent)
验证器(Validator)
上游/下游(upstream/downstream)
内向/外向(inbound/outbound)
把HTTP协议的官方定义进行归纳,得出 HTTP协议的 4 个关键点:
(1) HTTP 是建立在 TCP/IP 协议之上,面向应用层的超文本传输协议。
(2) 它由请求和响应组成,完全符合标准的客户端服务器的请求响应模型。
(3) 协议很轻便简单,并且请求与请求间没有关联,是无状态的协议。
(4) 为了弥补这种无状态性就需要使用 HTTP 协议的扩展 Cookie 等方式建立关联。

2.2 HTTP 协议原理

HTTP 协议工作于客户端-服务端的架构上。客户端通过 URL 向服务器发送所有请求。服务器根据接收到的请求,向客户端发送响应信息。 HTTP 协议定义客户端如何向服务器发送请求,以及服务器如何将响应请求传送给客户端,所以 HTTP 协议采用了请求/响应模型。

a.客户端
客户端主要有两个职能。
(1) 一个向服务器发送请求。
(2) 接收服务器返回的报文并解析成友善的信息供我们阅读。
客户端大概有以下几类: 浏览器、应用程序(桌面应用和 app应用)等。
日常生活中使用最多的就是浏览器。我们在地址栏输入网址并回车,浏览器会为我们做如下处理。
(1) 解析出协议 (HTTP) 、域名(www.qq.com)。
(2) 使用 HTTP 协议并创建请求报文向服务器端发送请求。
(3) 接收到服务器返回的内容并经过渲染后展示给用户。
测试人员日常使用的截包工具大多数都有模拟请求发送的功能。例如,postman、fiddler 等。

b.服务器
服务器端在接收到客户端发送的请求后会开始处理请求。
服务端的处理过程如下。服务器软件一直在监听端口是否有新的请求到达,如 iis 或 tomcat 在建立 Web 站点后,默认会一直监听 80 端口等待 HTTP请求到达服务器。
(1) 建立连接:如果客户端已经打开一条到服务器的持久连接,则可以直接使用,否则,客户端需要在服务器打开一条新的连接。
(2) 接收请求报文:连接上有数据到时,Web 服务器会从网络连接中读取数据,并将请求报文中的内容解析出来。
(3) 接收后会被如下表示。
(4) 处理请求: 当请求被接收和表示后,服务器便可以根据请求报文进行处理了。例如,post 方法中提出报文主体的数据并插入到数据库中。
(5) 访问资源:请求处理完成后,比如 Web 会根据数据生成一系列的 HTML 页面或图片等信息,此步骤将访问这些存储在服务器上的物理文件。
(6) 构建响应: Web 服务器在识别资源后,构造响应报文。响应报文中包含状态码、响应头、主体等内容。
(7) 发送响应: 服务器将响应的数据发送给客户端机器。
(8) 记录日志:请求结束,Web 服务器会在日志文件中添加一条请求记录。

c. 报文
客户端与服务器端之间的信息传递使用的载体叫作报文。报文分为请求与响应两部分。
(1) 客户端向服务器发送一个请求报文。
请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。

(2) 服务器反馈给客户端一个响应报文。
响应的内容包括协议的版本、成功或者错误响应码、服务器信息、响应头部和响应数据。

2.3 Uniform Resource Locator

假设请求发送地址为:www.example.com/index.html
浏览器会将地址解析为:
Host: www.example.com
Name: Uri Value: index.html
其中的 URI 就是 HTTP 所使用的统一资源标识符(Uniform Resource Identifiers),用来传输数据和建立连接。而我们日常使用的 URL 则是一种特殊类型的 URI,包含了用于查找某个资源的足够的信息。
URL 的全称是 Uniform Resource Locator,是互联网上用来标识某一处资源的地址。
URL 主要有三个作用:
(1) HTTP 是 URL 的方案,方案告诉客户端使用什么样的协议去访问服务器。
(2) Host: www.example.com ,指服务器的位置。
(3) /index.html 是资源路径,说明了请求的是服务器上哪个特定的本地资源。

我们以链接 http://www.kath2.com/news/index.asp? ID=210&page=1#name 为例,对 URL进行详解。
URL 一般分为以下几个部分。
(1) 协议部分:该 URL 的协议部分为 “HTTP: ”, 这代表网页使用的是 HTTP 协议。在 Internet 中可以使用多种协议,如 HTTPS、Ftp 等。在 “HTTP” 后面的 ‘‘//’’ 为分隔符。
(2) 域名部分:该 URL 的域名部分”www.kath2.com”。 一个 URL 中,也可以使用 IP 地址作为域名使用。
(3) 端口部分:跟在域名后面的是端口,域名和端口之间使用 ”:” 作为分隔符。端口不是一个 URL 必需的部分,如果省略端口部分,将采用默认端口。例如,HTTP的默认端口为 80, HTTPS 的默认端口为 443。
(4) 虚拟目录部分:从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。虚拟目录也不是一个 URL 必需的部分。本例中的虚拟目录是 “/news/”。
(5) 文件名部分: 从域名后最后一个 “/” 开始到 “?” 为止,是文件名部分。
(6) 如果没有 “?” ,则是从域名后的最后一个 “/” 开始到”#"为止,是文件名部分。
(7) 如果没有 ”?” 和 “#”,那么从域名后的最后一个“/” 开始到结束,都是文件名部分。本例中的文件名是 “index.asp”。文件名部分也不是一个 URL 必需的部分,如果省略该部分,则使用默认的文件名。
(8) 锚部分:从“#” 开始到最后,都是锚部分。本例中的锚部分是“name”。锚部分也不是一个 URL 必需的部分。
(9) 参数部分:从“?” 开始到“#” 为止之间的部分为参数部分,又称为搜索部分、查询部分。本例中的参数部分为 “ID=210&page=1”。可以允许有多个参数,参数与参数之间用 “&”作为分隔符。

2.4 请求报文(request)

a. 报文格式
request 报文的结构分为 3 部分。
(1) 请求行(request line)
(2) 请求头部(header)
(3) 主体(body)

b.请求报文的 headers 属性。
header 的属性有很多,比较难以记忆。 Fiddler 把 header 进行了分类,这样比较清晰,也容易记忆。header 的属性包含以下几部分。
(1) Cache 头域。
Cache-Control、If-Modified-Since、If-None-Match、Pragma
(2) Client 头域
Accept、User-Agent、Accept-Charset
(3) Cookie 头域
Cookie 最重要的 header, 将 Cookie 的值发送给 HTTP 服务器。
(4) Miscellaneous 头域。
(5) Entity 头域
Content-Length、Control-Type、另外一种常见的媒体格式是上传文件之时使用的。
(6) Transport 头域
Connection
Connection: keep-alive
Connection:close

c.请求报文的方法。
请求的起始行以方法作为开始,方法用来告诉服务器要如何做。
在开发中通常有两种请求方式。
(1) get 方式:是以实体的方式得到由请求 URI 所指定资源的信息,如果请求 URI 只是一个数据产生过程,那么最终要在响应实体中返回的是处理过程的结果所指向的资源,而不是处理过程的描述。

(2) post 方式:用来向目的服务器发出请求,要求它接收被附在请求后的实体,并把它当作请求队列中请求 URI 所指定资源的附加新子项,所以 post 请求可能会导致新的资源的建立和/或已有资源的修改。

除了以上两种常用请求方式,还有另外五中请求方法。说明如下。
a. HEAD: 类似于 get 请求,只不过返回的响应中没有具体的内容,用于获取报头。
b.DELETE: 请求服务器删除指定的的页面。
c.CONNECT: HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
d.OPTIONS: 允许客户端查看服务器的性能。
e.TRACE: 回显服务器收到的请求,主要用于测试或调试。

***** get 与 post 的区别:******
(1) 根据 HTTP 规范,get 用于信息获取,而且应该是安全的和幂等的。
post 表示可能会修改服务器上资源的请求。
用通俗的话来说,我们可以从两个角度看待 get 请求。
A. 从发送请求的角度,get 请求相当于我们在数据库中做了查询的操作,这样的操作不影响数据库本身的数据。
B.从接收返回数据的角度,幂等的含义简单地说就是发送 get 请求不改变返回数据的内容。
这样说似乎有点抽象,举个例子:
例如,你发送 get 请求获取测试论坛的首页信息。首页信息并不会因为你发了请求而改变。因为 get 用于不改变返回信息内容的请求,所以 HTTP 规范定义它是安全的,就像对数据库不做增删改操作,只查询数据一样。
而 post 的用途呢,表示会改变服务器上所返回资源信息的请求,相当于我们在数据库中做了修改的操作,会影响数据库本身的数据。
例如,你在测试论坛上发了帖子,做了评论,得到了积分等。这种情况下,资源状态被改变了,所以 HTTP 规范定义 post 请求是可能会改变服务器资源的请求。

通过 HTTP 规范的定义,我们可以看出 get 和 post 都是用作传递及获取服务器信息的请求。get 请求也可以向服务器传递数据,post 请求也需要服务器返回数据。

(2) 关于 get 和 post 表现形式的不同。
get 请求的数据会附在 URL 之后(就是把数据放置在 HTTP 协议头中), 以 ? 分割 URL 和传输数据,多个参数用 & 连接。post 请求就是把提交的数据放置在 HTTP 包的 body 中。这种形式是 HTML 标准对 HTTP 协议用法的约定,并不能作为 post 和 get 请求的区别。现在我们也有很多的 Web Server 支持 get 中包含 body 的表现形式。

(3) 获取请求变量的值是由服务器端配置所决定的。这些与 post 和 get 请求的区别完全没有关系。

(4) 关于传送数据量的问题
在 HTTP 协议规范中,没有对传输的数据大小进行限制,也没有对 URL 长度进行限制。如果说对于用 get请求 URL 上有限制的话,取决于以下两方面。
a.HTTP 客户端浏览器自己的限制:如 IE 限定 URL 长度为 2083 字节, opera 是 4050,Netscape 是 8192 等。
b.Web 服务器为了效率及安全的考虑,所以修改 Apache、IIS 的配置对 post 提交数据大小进行的限制。

(5) 关于安全性。
关于 get 与 post 的安全性,即使 post 请求在 URL 上看不到传数数据也不能说 post 安全。如果你使用截数据包的工具查看没有加密过的 post 请求,同样可以清晰看到 post 报文的内容。所以说,安全不安全根本不是 get 和 post 的区别,只和两者是否加密有关。

2.5 响应报文(response)
  1. 报文格式
    response 消息的结构和 request 消息的结构基本一样,同样也分为三部分。
    a. 响应状态(response code)
    b. 响应头(response header)
    c.响应主体 (response body)

  2. 响应报文的 headers 属性。
    (1) Cache 头域
    Cache-Control、Date、 Expires、Pragma
    (2) Cookie/Login 头域
    p3p、Set-Cookie
    (3) Entity 头域
    ETag、Last-Modified、Content-Length、Content-Language
    (4) Miscellaneous 头域
    Server、 X-AspNet-Version、X-Powered-By
    (5) Transport 头域
    在此需要为测试人员明确一个容易混淆的概念:HTTP 协议的无状态和 Connection: keep-alive 是两个不同的概念。无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。从另一方面讲,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系。HTTP 是一个无状态的、面向连接的协议,无状态不代表 HTTP 不能保持 TCP 连接,更不能代表 HTTP 使用的是 UDP 协议(无连接)。
    从 HTTP/1.1 开始,默认都开启了 keep-Alive, 保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。keep-Alive 不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如 Apache) 中设定这个时间。
    (6) Location 头域
    用于重定向一个新的位置,包含新的 URL 地址。
    (7) Security 头域

  3. 响应报文的状态码
    当客户端发起一次 HTTP 请求后,服务器会返回一个包含 HTTP 状态码的信息头用于响应客户端的请求。 response 消息中的第一行叫做 状态行,由 HTTP 协议版本号、状态码、状态消息三部分组成。
    状态码用来告诉 HTTP 客户端 HTTP 服务器是否产生了预期的 response。状态码总共只有三位,第一位表示状态类别,共分为五种。
    1xx: 是进度通知类状态,意思是说:请求我已经收到了,或你的请求我正在处理。
    2xx: 表示:你的请求我已经成功处理了。
    3xx: 即重定向,也就是服务器告诉客户端:你要的资源搬家了,你到某某地方再去找找。
    4xx: 客户端发来的响应报文里有些错误,比如语法错误或请求的资源不存在等。
    5xx: 服务器有些问题,已经无法处理完成你的请求了。

2.6 HTTP 扩展
a. cache 的运用

服务器收到请求时,会在响应中回送该资源的 Last-Modified 和 ETag 头,客户端将该资源保存在 Cache 中,并记录这两个属性。当客户端需要发送相同的请求时,会在请求中携带 If-Modified-Since 和 If-None-Match 两个头。两个头的值分别是响应中 Last-Modified 和 ETag 头的值。服务器通过这两个头判断本地资源未发生变化,客户端不需要重新下载,返回 304 响应。
缓存的目的是为了在很多情况下减少发送请求,同时在许多情况下可以不需要发送完整响应。前者减少了网络回路的数量, HTTP 利用一个“过期(expiration)” 机制来实现此目的。后者减少了网络应用的带宽,HTTP 用 “验证(validation)” 机制来实现此目的。

断电续传的原理就是使用了 GET 方法的属性。
HTTP 协议的 get 方法,支持只请求某个资源的某一部分。
(1) 206 Partial Content: 部分内容响应。
(2) Range: 请求的资源范围。
(3) Content-Range: 响应的资源范围。
在连接断开重连时,客户端只请求该资源未下载的部分,而不是重新请求整个资源,来实现断点续传。

分块请求资源实例如下。
(1) Range: byte=407802-: 请求这个资源从 407802 个字节到末尾的部分。
(2) Content-Range: bytes 407802 - 713545 / 713546: 响应中指示携带的是该资源的 407802 ~ 713545 的字节,该资源共 713546 个字节。
客户端通过并发的请求相同资源的不同片段,来实现对某个资源的并发分块下载,从而达到快速下载的目的。

多线程下载的原理如下:
(1) 下载工具开启多个发出 HTTP 请求的线程。
(2) 每个 HTTP 请求只请求资源文件的一部分:Content-Range: bytes 407802 - 713545 / 713546.
(3) 合并每个线程下载的文件。

Cache-Control 指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置 Cache-Control 并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括 no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,响应消息中的指令包括 public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age.

通常缓存分为 强缓存 和 协商缓存。

b. Cookie 的运用

HTTP 协议中与 Cookie 相关的属性如下。
(1) Cookie: 客户端将服务器设置的 Cookie 返回到服务器。
(2) Set-Cookie: 服务器向客户端设置 Cookie。
(3) Cookie2(RFC2965): 客户端指示服务器支持 Cookie 的版本。
(4) Set-Cookie2(RFC2965); 服务器向客户端设置 Cookie。

服务器在响应消息中用 Set-Cookie 头将 Cookie 的内容送给客户端,客户端在新的请求中将相同的内容携带在 Cookie 头中发送给服务器,从而实现会话的保持。

c. Session 的运用

当程序需要为某个客户端的请求创建一个 Session 的时候,服务器首先检查这个客户端的请求里是否已包含了一个 Session 标识,称为 Session ID。如果已包含一个 Session ID,则说明以前已经为此客户端创建过 Session,服务器就按照 Session ID,则为此客户端创建一个 Session,并且生成一个与此 Session 相关联的 Session ID. Session ID 的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个 Session ID 将被在本次响应中返回给客户端保存。

Session 有两种实现方式。
(1) 使用 Cookie 来实现
服务器给每个 Session 分配一个唯一的 JSESSIONID,并通过 Cookie 发送给客户端。
当客户端发起新的请求的时候,将在 Cookie 头中携带这个 JSESSIONID。这样服务器能够找到这个客户端对应的 Session。

(2) 使用 URL 回写来实现。
URL 回写是指服务器在发送给浏览器页面的所有链接中都携带 JSESSIONID 的参数,这样客户端点击任何一个链接都会把 JSESSIONID 带回服务器。
如果直接在浏览器输入服务端资源的 url 来请求该资源,那么 Sesson 是匹配不到的。
Tomcat 对 Session 的实现,是一开始同时使用 Cookie 和 URL 回写机制,如果发现客户端支持 Cookie ,就继续使用 Cookie,停止使用 URL 回写。如果发现 Cookie 被禁用,就一直使用 URL 回写。jsp 开发处理到 Session 的时候,对页面中的链接会使用 response.encodeURL()。

Token 的应用

运用 Token,服务器就不用再保存 Session ID,只负责生成 Token ,然后验证 Token。Token 的传递通常被放在 Cookie 中,如果客户端不支持 Cookie ,Token 也可以放置在请求头中。和 Cookie 一样,为了数据安全性,Token 中不应该放如密码等敏感信息。

3.HTTPS 协议详解

HTTP 协议通常承载于 TCP 协议之上,有时也承载于 TLS 或 SSL 协议层之上,这个时候,其就成了我们常说的 HTTPS。HTTPS ,是以安全为目标的 HTTP 通道,简单讲就是 HTTP 的安全版。

3.1 加密算法

a. 对称加密
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法就称为对称加密,也称为单密钥加密。对称加密的密钥只有一个,加密解密为同一个密码,且加密解密速度快,典型的对称加密算法有 DES、AES等。

b. 非对称加密
密钥成对出现(根据公钥无法推知私钥,根据私钥也无法推知公钥),加密解密使用不同密钥(公钥加密需要私钥解密,私钥加密需要公钥解密),相对对称加密速度较慢,典型的非对称加密算法有 RSA、DSA等。

由于非对称加密速度较慢,则可以对两者进行结合。首先生成一个对称加密算法的密钥,用非对称加密的方式安全发给对方。随后就不用非对称加密了,只用这个密钥,利用对称加密算法来通信。

3.2 数字签名

A 跟 B 通信,A 把他的公钥和个人信息用一个 Hash 算法生成一个信息摘要,这个 Hash 算法有一个极好的特性,只要输入数据有一点点的变化,那生成的摘要数据就会有巨变,这样就可以防止别人修改原始内容。随后让有公信力的认证中心(简称 CA ) 用它的私钥对信息摘要加密,形成签名:把原始信息和数据签名合并,形成一个全新的东西,叫做 “数字证书”。当 B 把自己的证书发给 A 的时候,A 就用同样的 Hash 算法,再次生成信息摘要,然后再用 CA 的公钥对数字签名解密,得到 CA 创建的信息摘要,两者进行对比就知道有没有被篡改了。

3.3 传输过程

(1) 客户端发起 HTTPS 请求
用户在浏览器里输入一个 HTTPS 网址连接到服务器端口。

(2) 服务器端初步响应
采用 HTTPS 协议的服务器必须有一套数字证书,这套证书其实就是一对公钥和私钥。将证书发回给客户端,证书包含证书的颁发机构、过期时间等。

(3) 客户端解析证书
客户端首先会验证证书是否有效,比如颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致、过期时间等,如果发现异常,则提示证书存在问题。如果证书没有问题,那么客户端就生成一个随机值,然后用证书对该随机值进行加密。

(4) 客户端发送加密信息
客户端发送的是用证书加密后的公钥。

(5) 服务器解密信息
服务器端用私钥解密后,得到了客户端传过来的公钥,然后把内容通过该值进行对称加密。

(6) 服务器发送加密后的信息
服务器发送用公钥进行加密后的信息。

(7) 客户端解密信息
客户端用之前生成的私钥解密服务器端传过来的信息,客户端就获取了解密后的内容。

4. WebSocket 协议详解

4.1 WebSocket 的由来

HTTP 会存在以下三个关键缺点。
(1) HTTP 协议是符合请求响应模型基本特征的。
(2) HTTP 协议的服务器端不能主动给客户端发送请求,一次连接的建立只能由客户端发起。所以 HTTP 协议对于服务器端来说是被动发起请求的。
(3) HTTP 协议的无状态性,请求与请求间是没有关联的。

HTTP long poll 实现原理:
long poll 是指客户端发起连接后,如果没消息,就一直不返回 response 给客户端。直到有消息才返回,返回之后,客户端再次建立连接,周而复始。从而可以看出 long poll 其实是很消耗服务器资源的,需要长时间响应和处理并发的能力。

ajax 轮询的实现原理:
ajax 轮询就是让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。

从以上我们可以看出,ajax 轮询需要服务器有很快的处理速度和资源。而 long poll 需要有很高的并发,也就是说同时接待客户的能力。所以问题就在于要解决这种过度消耗资源。

在 HTML5 规范中,定义了 WebSocket API。WebSocket API 是下一代客户端-服务器的异步通信方法。该通信取代了单个的 TCP 套接字,使用 ws 或 wss 协议,可用于任意的客户端和服务器程序。
WebSocket API 最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。WebSocket 并不限于以 Ajax (或 XHR) 方式通信,因为 Ajax 技术需要客户端发起请求,而 WebSocket服务器和客户端可以彼此相互推送信息;XHR 受到域的限制,而 WebSocket 允许跨域通信。

4.2 WebSocket 的属性

既然 WebSocket 如此好,那客户端如何通知服务器端它需要使用 WebSocket 协议呢?
首先 WebSocket 是基于 HTTP 协议的,它借用 HTTP 的协议来完成一部分握手工作。
然后服务器会返回响应信息,表示已经接收到请求,成功建立 WebSocket。至此,HTTP 已经完成它所有的工作,接下来就是完全按照 WebSocket 协议通信了。

4.3 WebSocket 的原理

WebSocket 解决了 HTTP 的缺点。当服务器完成协议升级后(HTTP–>websocket),服务器端就可以主动推送信息给客户端了。
WebSocket 实现原理场景如下:
客户端:哈喽,我要建立 WebSocket 协议,需要的服务:chat,WebSocket 协议版本:17 (HTTP Request)
服务端:ok,确认,已升级为 WebSocket 协议 (HTTP Protocols Switched)
客户端:麻烦你有信息的时候推送给我哦
服务端:ok,有的时候会告诉你的。
服务端:消息1
服务端:消息2
服务端:消息3
服务端:消息n

只需要经过一次 HTTP 请求,就可以做到源源不断地信息传送。(在程序设计中,这种设计叫做回调,即你有信息了再来通知我,而不是我傻乎乎地每次跑来问你。)
这样的协议也同时解决了 langloop 以及 Ajax 轮询的同步有延迟非常消耗资源的问题。我们所用的程序是要经过两层代理的,即 HTTP 协议在 Nginx 等服务器的解析下,然后再传送给相应的 Handler 来处理。简单地来说,我们有一个非常快速的接线员 Nginx,它负责把问题转交给相应的客服(Handler).
接线员基本上速度是足够的,但是每次都卡在客服(Handler),老有客服处理速度太慢,导致客服不够。WebSocket 就解决了这样一个难题,建立后,可以直接跟接线员建立持久连接。有信息的时候客服想办法通知接线员,然后接线员再统一转交给客户。这样就可以解决客服处理速度慢的问题了。
同时,在传统的方式上,要不断地建立、关闭 HTTP 协议。由于 HTTP 是无状态性的,每次都要重新传输 identify info 告诉服务器端你是谁。虽然接线员很快速,但是每次都要听这么一堆,效率也会有所下降,同时还得不断把这些信息转交给客服,不但浪费客服的处理时间,而且还会在网络传输中消耗过多的流量/时间。但是 WebSocket 只需要一次 HTTP 握手,所以说整个通信过程是建立在一次连接/状态中,也就避免了 HTTP 无状态性。服务端会一直知道你的信息,直到你关闭请求,这样就解决了接线员要反复解析 HTTP 协议,还要查看 identify info 的信息问题。
同时由客户主动询问,转换为服务器(推送)有信息的时候就发送(当然客户端还是等主动发送信息过来的),没有信息的时候就交给接线员(Nginx),不需要占用本身速度就慢的客服 (Handler)。

以上内容节选自 杨燕琳 —《Python 测试之道》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值