购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.1 Web应用程序基础

Web应用程序的运行基础是客户端/服务器架构。在此架构中,用户的Web浏览器,即客户端,会生成对特定资源的请求,并将这些请求发送至被称为Web服务器的计算机设备上。随后,Web服务器会通过网络将请求的资源传给客户端。术语“Web应用程序”通常用于指代那些在Web服务器上运行的软件程序,如维基百科、LinkedIn、Twitter、Gmail、GitHub和Reddit等。

尤为重要的是,Web应用程序针对终端用户进行了精心设计。相较于仅具备单向通信功能的网站,即从Web服务器传输至客户端,Web应用程序实现了双向通信,涵盖从服务器到客户端,以及从客户端至服务器的信息流动。以Reddit为例,这是一款充当互联网信息流动新闻源的Web应用程序。倘若它仅止于网站形态,访问者所能获取的仅限于网站背后组织提供的内容。然而,Reddit不同于静态网站,它赋予了用户通过发布、点赞、跟帖、评论、分享、举报不良帖子以及定制所需子社区等功能,与网站上的信息进行互动。

为了促使终端用户启用Web应用程序,必须实现Web浏览器与Web服务器之间的交互。终端用户通过在浏览器地址栏中输入URL来启动此交互。在1.1.1节中,我们将探讨后续操作。

1.1.1 URL

你可能已经知道统一资源定位符(URL)是用于定位互联网上唯一资源的地址。这个URL包含几个组成部分,在后面的章节中,当你构造API请求时,理解这些组成部分会很有帮助。所有的URL都包括使用的协议、主机名、端口、路径和任何查询参数,如下所示:

Protocol://hostname[:port number]/[path]/[?query][parameters]

协议是计算机通信所遵循的一套规则。URL中主要涉及的协议包括用于网页的HTTP、HTTPS和用于文件传输的FTP。

端口是用于指定通信通道的数字,仅在主机无法自动解析请求至正确端口时才会出现。通常情况下,HTTP通信发生在端口80上;HTTPS,即加密版的HTTP,使用端口443;而FTP则使用端口21。若要访问运行在非标准端口上的Web应用程序,可在URL中加入端口号,例如:https://www.example.com:8443(端口8080和8443分别是HTTP和HTTPS的常见替代端口)。

Web服务器上的文件目录路径用于指示URL中所指定的网页和文件位置。URL中所使用的路径与在计算机上定位文件的路径相似。

查询是URL的可选组件,具有执行搜索、过滤和翻译请求信息等功能。Web应用程序提供商亦可利用查询字符串来追踪特定信息,如引荐用户至网页的URL、会话ID或电子邮件。查询字符串以问号(?)开头,包含一组服务器编程处理的标识符。最后,查询参数为描述针对给定查询应执行操作的值。例如,跟随查询页面后的?lang=en可能表示向Web服务器指示应以英文提供所请求的页面。这些参数由Web服务器处理的另一组字符串组成。一个查询可包含多个由“&”分隔的参数。

为了使这些信息更具针对性,请参考URL(https://twitter.com/search?q=hacking&src=typed_query)。在此示例中,协议为https,主机名为twitter.com,路径为search,查询符号为?q(表示查询),查询参数为hacking,src=typed_query则是一个追踪参数。该URL是在Twitter Web应用程序的搜索栏中输入搜索词“hacking”并按下Enter键后自动生成的。浏览器被编程为以Twitter Web服务器可识别的方式构建URL,并收集一些追踪信息作为src参数。Web服务器将接收关于hacking内容的请求,并针对与hacking相关的信息做出响应。

1.1.2 HTTP请求

当终端用户通过Web浏览器访问特定URL时,浏览器会自动生成一个HTTP请求以获取相应的资源。所请求的资源通常是构成网页的文件,这些文件包含被请求的信息。此请求将通过互联网或网络路由发送至Web服务器,并在该处进行首次处理。若请求构造正确,Web服务器将把请求转发给Web应用程序。

代码清单1-1显示了对twitter.com进行身份验证时发送的HTTP请求。

代码清单1-1 对twitter.com进行身份验证时发送的HTTP请求
POST❶ /sessions❷ HTTP/1.1❸ 
Host: twitter.com❹ 
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 444
Cookie:_personalization_id=GA1.2.1451399206.1606701545; dnt=1;
 
username_or_email%5D=hAPI_hacker& ❺password%5D=NotMyPassword❻%21❼

HTTP请求由方法❶、资源路径❷和协议版本❸组成。方法部分将在后续的“HTTP方法”一节中进行详细描述,它表达了客户端对服务器的需求。在此,使用POST方法将登录凭证发送至服务器。路径可以包含整个URL、绝对路径或相对路径中的一个资源。此请求中,路径/sessions指明了处理Twitter认证请求的页面。

请求中包含一系列标头,这些键值对用于在客户端与Web服务器之间传递特定信息。标头以标头名称为始,后跟一个冒号(:),接着是标头的值。Host标头❹指定了域名主机,即twitter.com。User-Agent标头描述了客户端的浏览器和操作系统。Accept标头列出了浏览器能接收Web应用程序响应的各类内容。并非所有标头都是必需的,根据请求的需要,客户端和服务器可能包含其他未在此展示的标头。例如,此请求中包含一个Cookie标头,用于在客户端和服务器之间建立有状态的连接(关于此点,后续章节将有更多介绍)。欲了解更多关于各类标头的信息,请查阅Mozilla开发者页面关于标头的更多内容。

标头以下的部分为消息主体,即请求者试图让Web应用程序处理的信息。在此例中,主体包含用于认证Twitter账户的用户名❺和密码❻。主体中的某些字符会被自动编码,如感叹号(!)被编码为%21❼。对字符进行编码,是Web应用程序用来安全处理那些可能引发问题的字符的一种手段。

1.1.3 HTTP响应

Web服务器在接收到HTTP请求后,会依据一系列因素,如资源的可获取性、用户访问资源的授权状态、服务器的健康情况等,对该请求进行相应处理并返回响应。这些响应可能因各种条件的不同而有所差异。例如,代码清单1-2展示了对代码清单1-1中提出的请求的HTTP响应示例。

代码清单1-2 向twitter.com进行身份验证时的HTTP响应示例
HTTP/1.1❶ 302 Found❷
content-security-policy: default-src 'none'; connect-src 'self'
location: https://twitter.com/
pragma: no-cache
server: tsa_a
set-cookie: auth_token=8ff3f2424f8ac1c4ec635b4adb52cddf28ec18b8; Max-Age=157680000;
Expires=Mon, 01 Dec 2025 16:42:40 GMT; Path=/; Domain=.twitter.com; Secure; HTTPOnly;
SameSite=None
 
<html><body>You are being <a href="https://twitter.com/">redirected</a>.</body></html>

Web 服务器首先根据当前使用的协议版本(在本例中为HTTP/1.1❶)发出响应。HTTP 1.1是目前所采用的标准HTTP版本。状态码和状态信息❷将在1.1.4节中进行详细阐述,此处暂且为302 Found。302响应码意味着客户端成功通过身份验证,并将被重定向至客户端有权访问的目标页面。

注意,在HTTP中,响应部分亦包含响应标头,其作用在于为浏览器提供处理响应以及遵循安全要求的指导。set-cookie标头则是表明身份验证请求成功的另一项指标,由于Web服务器已发出一个包含auth_token的Cookie,客户端可以据此访问特定资源。响应消息主体位于响应标头之后。在此例中,Web服务器发送了一个HTML消息,提示客户端即将跳转至新页面。

所展示的请求与响应示例阐述了Web应用程序如何通过身份验证和授权来约束对其资源进行访问的普遍方法。Web身份验证是一个向Web服务器证实自身身份的过程,常见的验证形式包括提交密码、令牌或生物识别信息(如指纹)。若Web服务器接收了身份验证请求,它将通过赋予经过验证的用户访问特定资源的权限来表示授权。

在代码清单1-1中,我们观察到一个将用户名和密码发送至Twitter Web服务器(采用POST请求)的身份验证请求。Twitter Web服务器对成功的身份验证请求产生了302 Found的响应(见代码清单1-2)。set-cookie响应标头中的会话auth_token用于授权访问与hAPI_hacker Twitter账户相关联的资源。

注:

HTTP流量以明文形式传输,这意味着它在任何情况下都无法隐藏或加密。任何拦截代码清单1-1中的身份验证请求的人都可以阅读用户名和密码。为确保敏感信息的安全,HTTP请求可采用传输层安全性(TLS)进行加密,从而形成HTTPS。

1.1.4 HTTP状态码

在Web服务器对请求做出响应时,它会输出一个响应码和相应的响应消息。响应码用以表示Web服务器对请求的处理结果。事实上,响应码决定了客户端是否具备访问资源的权限。同时,它还可用于表明资源不存在、Web服务器存在故障,或请求的资源被重定向至其他位置等情况。代码清单 1-3 和代码清单 1-4 分别展示了200响应码与404响应码之间的差异。

代码清单1-3 200响应码的示例
HTTP/1.1 200 OK
Server: tsa_a
Content-length: 6552
 
<!DOCTYPE html>
<html dir="ltr" lang="en">
[...]
代码清单1-4 404响应码的示例
HTTP/1.1 404 Not Found
Server: tsa_a
Content-length: 0

200响应码表示客户端成功获取了所请求的资源,而404响应码则表明未找到所请求的资源,此时服务器可能会返回一个错误页面或空白页面。

由于Web API主要依赖于HTTP进行功能实现,因此了解从Web服务器接收到的响应码至关重要。HTTP响应码范围如表1-1所示。关于单一响应码或Web技术的其他信息,读者可查阅Mozilla的Web文档。Mozilla提供了大量关于Web应用程序架构的实用信息。

表1-1 HTTP响应码范围

1.1.5 HTTP请求方法

HTTP请求方法用于向Web服务器发起信息请求。此类请求方法亦被称为HTTP动词,包括GET、POST、PUT、HEAD、PATCH、OPTIONS、TRACE、CONNECT和DELETE等。

GET和POST分别为最常用的两种请求方法。GET请求旨在从Web服务器获取资源,而POST请求则用于向Web服务器递交数据。表1-2详细阐述了各个HTTP请求方法的相关信息。

表1-2 HTTP请求方法

一些请求方法具有幂等特性,即多次发送相同的请求不会改变Web服务器上资源的状态。举例来说,当执行开启灯光的操作时,灯光便会亮起。若灯光已处于开启状态,再次尝试开启开关,则开关仍保持开启,无任何变化。GET、PUT、HEAD、OPTIONS和DELETE等请求方法具有幂等特性。

相对而言,非幂等方法能够动态地改变服务器上资源的结果。非幂等方法包括POST、PATCH和CONNECT。POST是最常用于改变Web服务器资源的方法,用于在Web服务器上创建新资源。因此,若提交10次POST请求,将在Web服务器上创建10个新资源。反之,若使用具有幂等特性的PUT(通常用于更新资源)操作10次,则会对单个资源覆盖10次。

DELETE方法同样具有幂等特性,若发送10次删除资源的请求,资源仅会被删除一次,后续的请求则不会发生任何变化。Web API通常仅使用POST、GET、PUT、DELETE等方法,其中POST为非幂等方法。

1.1.6 有状态和无状态的HTTP

HTTP作为一种无状态协议,其在请求间并不保留任何跟踪信息。然而,在Web应用程序中,为确保用户能获得持续且一致的体验,Web 服务器有必要记录与客户端的HTTP 会话中的部分信息。例如,当用户登录账户并把若干项目添加至购物车时,Web应用程序需追踪终端用户购物车状态。否则,一旦用户浏览到其他Web页面,购物车将会被清空。

有状态连接使得服务器能够追踪客户端的操作、配置文件、图像、偏好等信息。此类连接采用名为Cookie的小型文本文件在客户端存储数据。Cookie可能保存站点特定设置、安全设置以及身份验证相关信息。与此同时,服务器通常会将数据存储在自身、缓存或后端数据库中。为了维持会话,浏览器会在请求中携带存储的Cookie。然而,在黑客攻击Web应用程序时,攻击者有可能通过窃取或伪造Cookie冒充终端用户。

在保持服务器与客户端有状态连接的过程中,存在一定的扩展限制。这种连接关系仅在创建状态时存在于特定的浏览器与服务器之间。若用户从一台计算机的浏览器切换至移动设备上的浏览器,客户端需要重新进行身份验证,并与服务器重新建立连接。此外,有状态连接要求客户端持续向服务器发送请求。当众多客户端与同一服务器维持状态时,服务器所能处理的计算资源便成为一大挑战。此类问题可通过无状态应用程序解决。

无状态通信不需要管理会话所需的服务器资源。在无状态通信中,服务器不保存会话信息,因此发送的每个无状态请求都必须包含足够的信息,使Web服务器能够判断请求者是否具备访问特定资源的权限。这类无状态请求可包含一个密钥或某种形式的授权标头,以实现与有状态连接相近的体验。与Web应用程序服务器上的会话数据不同,这些连接利用后端数据库来保存相关信息。

在购物车示例中,一种无状态应用程序可以通过修改包含特定令牌的请求所对应的数据库或缓存来追踪用户购物车的内容。虽然终端用户体验并未发生变化,但Web服务器处理请求的方式却有显著差异。由于维持了状态,每个客户端发出的请求所需的信息都可以在不丢失有状态连接中的信息的前提下,实现无状态应用程序的扩展。反之,只要请求中包含所有必要的信息,并且这些信息可以在后端数据库中查找,便可使用任意数量的服务器来处理请求。

在黑客攻击API时,攻击者可能通过窃取或伪造终端用户的令牌来实现冒充。API通信具有无状态特性,这是下一章将详细探讨的主题。 uZEdP+lD+cp2As7p+mXTuumOxUVgVsJ8HeZJeWkaZxfuHpCZtP8+Kdo4nRb4KaPv

点击中间区域
呼出菜单
上一章
目录
下一章
×