【Bug Bounty Hunter】第一章-网络请求

img

【Bug Bounty Hunter】笔记系列

0x00 HTTP基础知识

1. 超文本传输协议(HTTP)

HTTP通信由客户端和服务器组成,其中客户端向服务器发送请求。服务器收到请求后并返回所请求的资源。HTTP通信的默认端口是80,但可以根据Web服务器配置将其更改为其他端口。当我们通过浏览器访问不同的网站时候,都是通过输入URL(Uniform Resource Locator)来进行访问的。

1.1 URL

我们看一下URL的结构:

img

以下是每个组成部分所代表的含义:

组成部分 示例 说明
Scheme http:// https:// 用于标识客户端访问的协议,以://结尾。
User Info admin:password@ 这是一个可选组件,包含用于验证主机身份的凭据(用:分隔),并用@与主机分隔。
Host inlanefreight.com 主机表示资源位置,可以是主机名或IP地址。
Port :80 端口与主机之间用冒号:隔开。如果未指定端口http方案默认为80端口,https默认为443端口。
Path /dashboard.php 这指向被访问的资源,可以是文件或文件夹。如果没有指定路径,服务器将返回默认索引,如index.html
Query String ?login=true Query String 以?开头,由一个参数和一个值组成。多个参数之间可以用&分隔。
Fragments #status Fragments 由客户端的浏览器处理,用来定位页面资源的位置。

1.2 HTTP工作流程

img

上图展示了HTTP请求的流程。用户第一次在浏览器中输入URL(inlanefreight.com)时,它会向DNS(域名解析)服务器发送请求以解析该域并获取其IP。 DNS服务器查找 inlanefreight.com的IP地址并返回它。

注意:浏览器通常会先在本地/etc/hosts文件中查找记录,如果请求的域名不存在,然后他们会联系其他DNS服务器。我们可以使用/etc/hosts手动添加记录以进行DNS解析。

浏览器获得所请求域名的IP地址后,它就会向默认HTTP端口(例如80)发送GET请求,询问根(/)路径。然后,Web服务器接收请求并处理它。默认情况下,服务器配置是在收到 / 请求时返回索引文件。

在这种情况下,Web服务器将读取index.html的内容并将其作为HTTP响应返回。响应还包含状态代码(例如 200 OK ),这表明请求已成功处理。然后浏览器显示index.html内容并呈现给用户。

1.3 cURL

在本节中我们将通过两个重要的工具发送Web请求:浏览器(例如Chrome或Firefox)以及cURL命令行工具。

cURL 是一个命令行工具和库,主要支持HTTP以及许多其他协议。这使得它成为脚本和自动化的优秀工具。

我们可以通过cURL发送请求的信息,如下图:

1
d4rk30@linux$ curl google.com

我们看到与Web浏览器不同,cURL不会渲染HTML/JavaScript/CSS代码,而是以其原始格式打印它。同时我们还可以使用cURL下载页面或文件,使用-O会将内容输出到文件中。并且如果我想指定下载文件的名称,可以使用-o

1
2
3
d4rk30@linux$ curl -O inlanefreight.com/index.html -o 1.html
d4rk30@linux$ ls
index.html

如我们所看到的,这次没有直接显示网页的内容,而是保存到1.html中。并且cURL在处理请求时打印一些状态。我们可以使用-s来屏蔽这些内容的输出,如下所示:

1
d4rk30@linux$ curl -s -O inlanefreight.com/index.html -o 1.html

这次,cURL没有输出任何内容。最后,我们可以使用-h来查看cURL帮助信息,详细展示了其他参数的用法。

1
d4rk30@linux$ curl -h

2. 安全超文本传输协议(HTTPS)

HTTP的一个重要的问题是所有数据都以明文方式传输。这意味着在源和目标之间的任何人都可以执行中间人攻击(Man-in-the-middle,建成后MITM)来查看传输的数据。为了解决这个问题,HTTPS (HTTP Secure) 协议 应运而生,所有通信都以加密格式传输,因此即使第三方拦截了请求,也无法从中提取数据。因此,HTTPS已成为互联网网站的主流方案,而HTTP协议正在被逐步淘汰。

2.1 HTTPS概述

如果我们检查一个HTTP请求,就能看到浏览器和网站之间不安全通信的效果。例如,下面是一个HTTP登录请求的内容:

img

我们可以看到登录信息(账号和密码)使用明文显示。这样一来同一网络(如公共无线网络)中的其他人就可以轻松捕获请求,从而获取登陆信息。

相反,当有人拦截并分析来自HTTPS请求的流量时,他们会看到如下内容:

img

正如我们看到的,数据作为一个独立的加密信息流而进行传输,其他人想要获取这些数据变得非常困难。

注意:虽然通过HTTPS协议传输的数据可能会被加密,但如果请求联系明文DNS服务器,该请求仍然可能会泄露所访问的URL。因此,建议使用加密的DNS服务器(例如 8.8.8.8 或 1.1.1.1),或使用VPN服务以确保所有流量都正确加密。

2.2 HTTPS工作流程

让我们看看HTTPS是如何运行的:

img

如果我们输入http://而不是https://来访问强制执行HTTPS的网站,浏览器会尝试解析域并将用户重定向到托管目标网站的网络服务器。请求首先发送到端口80,这是未加密的 HTTP协议。服务器检测到此情况并将客户端重定向到安全HTTPS端口443。这是通过301 Moved Permanently响应完成的。

接下来,客户端(网络浏览器)发送一个”client hello”数据包,提供关于自己的信息。之后服务器回复”server hello”,接着进行密钥交换,交换SSL证书。客户端验证密钥/证书,并发送自己的密钥/证书。之后开始加密握手,以确认加密和传输是否正常。

一旦握手成功完成,正常的HTTP通信就会继续进行,并在此后进行加密。

注意:根据具体情况,攻击者可能会实施HTTP降级攻击,将HTTPS通信降级为HTTP,使数据以明文形式传输。具体方法是设置一个中间人代理,在用户不知情的情况下通过攻击者的主机传输所有流量。不过,大多数现代浏览器、服务器和网络应用程序都能防范这种攻击。

2.3 使用cURL处理HTTPS请求

一般情况下cURL会自动处理所有HTTPS通信标准,执行安全握手,然后自动加密和解密数据。不过,如果我们接触到一个SSL证书无效或过期的网站,那么cURL默认情况下不会继续通信,以防止前面提到的中间人攻击。

在测试本地Web应用程序或出于练习目的,访问测试的目标网站时,我们可能会遇到此类问题,因为此类Web应用程序可能尚未实现有效的SSL证书。要跳过cURL的证书检查,我们可以使用-k参数:

1
d4rk30@linux$ curl -k https://test.com

3. HTTP请求和响应

HTTP通信主要由HTTP请求和HTTP响应组成。 HTTP请求由客户端(例如 cURL/浏览器)发出,并由服务器(例如 Web 服务器)处理。请求包含我们需要从服务器获取的所有详细信息,包括资源(如URL、路径、参数等)。服务器接收HTTP请求,对其进行处理并通过发送HTTP响应进行响应,其中包含响应代码,并且可能包含资源数据(如果请求者有权访问它)。

3.1 HTTP请求

img

上图显示了对URL的HTTP GET请求:

任何HTTP请求的第一行都包含三个主要字段,“以空格分隔”:

字段 示例 说明
Method GET 指定要执行的操作类型的 HTTP 方法或动词。
Path /users/login.html 访问资源的路径。该字段也可以用查询字符串作为后缀(例如:?username=user)。
Version HTTP/1.1 第三个也是最后一个字段用于表示 HTTP 版本。

下一行包含HTTP header值对,例如Host、User-Agent、Cookie和许多其他可能的header。这些header用于指定请求的各种属性。header用换行结束,这是服务器验证请求所必需的。最后请求可能会以请求正文和数据结束。

注意:HTTP版本1.X以明文形式发送请求,并使用换行符分隔不同的字段和不同的请求。另一方面,HTTP版本2.X以字典形式的二进制数据发送请求。

3.2 HTTP响应

img

HTTP响应的第一行包含两个以空格分隔的字段。第一个是HTTP版本(例如 HTTP/1.1 ),第二个表示HTTP响应代码(例如200 OK)。

响应代码用于确定请求的状态,在第一行之后,响应列出了其header ,类似于HTTP请求。

最后,响应可能以响应正文结束,响应正文在header后面用换行分隔。响应正文通常定义为HTML代码。但是,它还可以响应其他代码类型(例如JSON)、网站资源(例如图像、样式表或脚本),甚至是文档(例如托管在网络服务器上的PDF文档)。

3.3 用cURL查看请求与响应内容

在我们之前使用cURL的示例中,我们仅指定URL并获取返回的响应正文。然而,cURL还允许我们预览完整的HTTP请求和完整的HTTP响应,要查看完整的HTTP请求和响应,我们只需将-v(verbose)添加到之前的命令中,它就会打印请求和响应:

1
d4rk30@linux$ curl google.com -v

-vvv 显示更详细的输出。尝试使用此参数来查看显示了哪些额外的请求和响应详细信息。

4. HTTP Headers

HTTP Headers可以有一个或多个值,附加在Header名称后面并用冒号分隔。我们可以将Headers分为以下几类:

  • General Headers (通用标头)
  • Entity Headers (实体标头)
  • Request Headers (请求标头)
  • Response Headers (响应标头)
  • Security Headers (安全标头)

4.1 General Headers

General Headers 用于HTTP请求和响应。它们是上下文相关的,用于描述消息而不是其内容。

Header 示例 说明
Data Date: Wed, 16 Feb 2022 10:38:44 GMT 表示信息发出的日期和时间。最好将时间转换为标准 UTC 时区。
Connection Connection: close 指示当前网络连接是否应在请求结束后保持激活状态。该Header的两个常用值是close和keep-alive。客户端或服务器的close值表示他们希望终止连接,而 keep-alive 标头则表示连接应保持开放以接收更多数据和输入。

4.2 Entity Headers

与General Headers类似,Entity Headers可同时用于请求和响应。这些标头用于描述消息传输的内容(实体)。它们通常出现在响应POST或PUT请求中。

Header 示例 说明
Content-Type Content-Type: text/html 用于描述传输的资源类型。该值由浏览器在客户端自动添加,并在服务器响应中返回。charset 字段表示编码标准,如 UTF-8。
Media-Type Media-Type: application/pdf Media-Type 与 Content-Type 类似,描述传输的数据。该 Header 对服务器解释我们的输入起着至关重要的作用。字符集字段也可与该标头一起使用。
Boundary boundary=”b4e4fbd93540” 当同一信息中有多个内容时,作为分隔内容的标记。例如,在表单数据中,该边界会被用作 --b4e4fbd93540 来分隔表单的不同部分。
Content-Length Length Content-Length: 385 表示所传递实体的大小。服务器使用该 Header 从报文正文中读取数据,浏览器和 cURL 等工具会自动生成该标头。
Content-Encoding Content-Encoding: gzip 数据在传递之前可以进行多重转换。例如,可以对大量数据进行压缩,以减小信息的大小。使用的编码类型应使用 Content-Encoding Header 指定。

4.3 Request Headers

客户端在HTTP事务中发送Request Headers。这些Headers用于HTTP请求,与信息内容无关。以下是HTTP请求中常见的标头。

Header 示例 说明
Host Host: www.inlanefreight.com 用于指定查询资源的主机。可以是域名或 IP 地址。HTTP 服务器可配置为不同网站的主机,这些网站可根据主机名显示。这使得 Host Header 成为一个重要的枚举目标,因为它可以显示目标服务器上是否存在其他主机。
User-Agent User-Agent: curl/7.77.0
Referer Referer: http://www.inlanefreight.com/ 表示当前请求来自哪里。例如,点击谷歌搜索结果中的链接会使 https://google.com 成为引用者。信任这个标头是很危险的,因为它很容易被操纵,导致意想不到的后果。
Accept Accept: / Accept Header 描述了客户端可以理解的媒体类型。它可以包含多个媒体类型,以逗号分隔。*/* 值表示接受所有媒体类型。
Cookie Cookie: PHPSESSID=b4e4fbd93540 包含 name=value 格式的 Cookie 值对。Cookie 是存储在客户端和服务器上的一段数据,用作标识符。每次请求都会将这些数据传递给服务器,从而保持客户端的访问权限。Cookie 还可用于其他目的,如保存用户偏好或会话跟踪。一个标头中可以有多个 Cookie,中间用分号隔开。
Authorization Authorization: BASIC cGFzc3dvcmQK 服务器识别客户的另一种方法。认证成功后,服务器会返回客户端独有的令牌。与 Cookie 不同,令牌只存储在客户端,由服务器根据每次请求进行检索。根据所使用的网络服务器和应用程序类型,有多种类型的身份验证类型。

可以在此处找到请求标头及其用法的完整列表。

4.4 Response Headers

Response Headers 可在HTTP响应中使用,但与内容无关。某些Response Headers(如年龄、位置和服务器)用于提供有关响应的更多上下文。以下是HTTP中常见的Response Headers

Header 示例 说明
Server Server: Apache/2.2.14 (Win32) 包含处理请求的 HTTP 服务器的信息。它可用于获取服务器的信息(如版本)并进一步枚举。
Set-Cookie Set-Cookie: PHPSESSID=b4e4fbd93540 包含客户端识别所需的 cookie。浏览器会解析 cookie 并将其存储起来,以备将来请求之用。该 Header 的格式与 Cookie request header 相同。
WWW-Authenticate WWW-Authenticate: BASIC realm=”localhost” 通知客户端访问请求资源所需的身份验证类型。

4.5 Security Headers

最后是 Security Headers。随着浏览器种类的增多和基于网络的攻击的增加,有必要定义某些增强安全性的Header。HTTP Security Headers是一类响应Header ,用于指定浏览器在访问网站时应遵循的某些规则和策略。

Header 示例 说明
Content-Security-Policy Content-Security-Policy: script-src ‘self’ 规定网站对外部注入资源的策略。这可以是JavaScript代码,也可以是脚本资源。该Header指示浏览器只接受来自特定可信域的资源,从而防止跨站脚本 (XSS) 等攻击。
Strict-Transport-Security Strict-Transport-Security: max-age=31536000 防止浏览器通过明文HTTP协议访问网站,并强制所有通信通过安全的HTTPS协议进行。这样,攻击者就无法嗅探网络流量和访问受保护的信息,如密码或其他敏感数据。
Referrer-Policy Referrer-Policy: origin 决定浏览器是否应包含通过Referer标头指定的值。它有助于避免在浏览网站时泄露敏感的URL和信息。

注意:本节只提及一小部分常见的 HTTP 标头。HTTP 通信中还可以使用许多其他上下文标头。应用程序也可以根据自己的需求定义自定义标头。标准 HTTP 标头的完整列表可在此处找到

4.6 使用cURL查看Headers内容

在上一节中,我们看到了如何使用 cURL 的-v来显示HTTP请求和响应的全部细节。如果我们只想查看response headers,那么可以使用-I发送HEAD请求,并只显示response headers。此外,我们可以使用-i来显示头部和响应正文(例如HTML代码)。两者的区别在于,-I发送的是HEAD请求(将在下一节中介绍),而-i发送的是我们指定的任何请求,并同时打印Headers信息。

下面的命令显示了使用-I的输出示例:

1
d4rk30@linux$ curl -I google.com

除了查看Headers信息外,cURL还允许我们使用-H设置Request Headers信息,我们将在后面的章节中看到这一点。有些Headers,如User-Agent或Cookie标头,有自己的参数。例如,我们可以使用-A来设置User-Agent,如下所示:

1
d4rk30@linux$ curl -I google.com -A 'Mozilla/5.0'

0x01 HTTP方法

1. HTTP方法和代码

HTTP支持多种访问资源的方法。在HTTP协议中,多种请求方法允许浏览器向服务器发送信息、表单或文件。除其他外,这些方法用于告诉服务器如何处理我们发送的请求以及如何回复。

我们在前面部分测试的HTTP请求中看到了不同的HTTP方法。使用cURL,如果我们使用-v预览完整请求,第一行包含HTTP方法(例如GET/ HTTP/1.1 ),而使用浏览器开发工具,HTTP方法将显示在Method列中。此外,response headers还包含HTTP响应代码,该代码说明了处理HTTP请求的状态。

1.1 请求方法

以下是一些常用的方法:

Method 说明
GET 请求特定资源。附加数据可通过 URL 中的查询字符串(如 ?param=value)传递给服务器。
POST 向服务器发送数据。它可以处理多种类型的输入,如文本、PDF和其他形式的二进制数据。这些数据会附加在请求正文中,出现在标头之后。POST方法通常用于发送信息(如表单/登录)或向网站上传数据(如图像或文档)。
HEAD 请求向服务器发出 GET 请求时返回的Headers信息。它不会返回请求正文,通常用于在下载资源前检查响应长度。
PUT 在服务器上创建新资源。允许使用这种方法而不进行适当控制,可能会导致上传恶意资源。
DELETE 删除网络服务器上的现有资源。如果安全措施不当,可能会删除网络服务器上的关键文件,从而导致拒绝服务(DoS)。
OPTIONS 返回有关服务器的信息,如服务器接受的方法。
PATCH 对指定位置的资源进行部分修改。

该列表仅突出显示了一些最常用的HTTP方法。特定方法的可用性取决于服务器以及应用程序配置。有关 HTTP 方法的完整列表,您可以访问此链接

注意:大多数现代Web应用程序主要依赖GET和POST方法。但是,任何使用REST API 的Web应用程序也依赖于PUT和DELETE ,它们分别用于更新和删除API端点上的数据。有关更多详细信息,请参阅Web 应用程序简介模块。

1.2 响应代码

HTTP 态代码用于告诉客户端其请求的状态。 HTTP服务器可以返回五种类型的响应代码:

Type 说明
1XX 提供信息,不影响对申请的处理。
2XX 当请求成功时返回。
3XX 服务器重定向客户端时返回。
4XX 表示客户端请求不当。例如,请求不存在的资源或请求不良格式。
5XX 当HTTP服务器本身出现问题时返回。

以下是上述每种HTTP方法类型的一些常见示例:

Code 说明
200 OK 请求成功时返回,响应体通常包含请求的资源。
302 Found 将客户端重定向到另一个URL。例如,在成功登录后将用户重定向到其仪表板。
400 Bad Request 遇到畸形请求(如缺少行结束符的请求)时返回。
403 Forbidden 表示客户端没有适当的资源访问权限。当服务器检测到用户的恶意输入时,也会返回该值。
404 Not Found 当客户端请求的资源在服务器上不存在时返回。
500 Internal Server Error 当服务器无法处理请求时返回。

有关标准HTTP响应代码的完整列表,您可以访问此链接。除了标准的HTTP代码之外,各种服务器和提供商(例如 CloudflareAWS)还实现了自己的代码。

2. GET

每当我们访问任何URL时,我们的浏览器都会默认使用GET请求来获取该URL上托管的远程资源。一旦浏览器收到它请求的初始页面;它可以使用各种HTTP方法发送其他请求。

2.1 HTTP基本身份验证

当我们访问一些网站时,它会提示我们输入用户名和密码。与使用HTTP参数来验证用户凭据(例如 POST 请求)的常用登录表单不同,这种类型的身份验证使用basic HTTP authentication由Web服务器直接处理的来保护特定页面/目录,而不直接与Web应用程序交互。

我们尝试使用cURL访问该页面,然后添加-i以查看响应标头:

1
2
3
4
5
6
7
8
9
10
d4rk30@linux$ curl -i http://<SERVER_IP>:<PORT>/
HTTP/1.1 401 Authorization Required
Date: Mon, 21 Feb 2022 13:11:46 GMT
Server: Apache/2.4.41 (Ubuntu)
Cache-Control: no-cache, must-revalidate, max-age=0
WWW-Authenticate: Basic realm="Access denied"
Content-Length: 13
Content-Type: text/html; charset=UTF-8

Access denied

正如我们所看到的,我们获得Access denied了响应正文,并且 WWW-Authenticate 的Header信息中展示了Basic realm=”Access denied”,这确认了该页面确实使用了basic HTTP auth。我们在cURL中使用-u参数来发送验证信息:

1
d4rk30@linux$ curl -u admin:admin http://<SERVER_IP>:<PORT>/

这次我们在响应信息中可以看到页面内容。我们还可以通过另外一种方式提供的basic HTTP auth信息,进行验证:

1
d4rk30@linux$ curl http://admin:admin@<SERVER_IP>:<PORT>/

2.2 HTTP授权Header

让我们对上述命令添加一个-v参数:

1
d4rk30@linux$ curl -v http://admin:admin@<SERVER_IP>:<PORT>/

我们可以看到HTTP请求将Authorization Header设置为 Basic YWRtaW46YWRtaW4=,这是base64对admin:admin进行编码之后得到的。如果我们使用现代的身份验证方法(例如JWT),则Authorization将是Bearer类型,并将包含更长的加密令牌。

让我们尝试手动设置Authorization,而不提供凭据,看看它是否允许我们访问该页面。我们可以使用-H参数设置Headers,并将使用与上述HTTP请求相同的值。我们可以多次添加-H来指定多个Header:

1
d4rk30@linux$ curl -H 'Authorization: Basic YWRtaW46YWRtaW4=' http://<SERVER_IP>:<PORT>/

正如我们所看到的,这也使我们能够访问该页面。这些是我们可以用来对页面进行身份验证的几种方法。大多数现代 Web 应用程序使用使用后端脚本语言(例如 PHP)构建的登录表单,该表单利用 HTTP POST 请求对用户进行身份验证,然后返回 cookie 来维持其身份验证。

3. POST

在上一节中,我们了解了 Web 应用程序如何使用 GET 请求来实现搜索和访问页面等功能。但是,每当 Web 应用程序需要传输文件或从 URL 移动用户参数时,它们都会使用 POST 请求。

HTTP POST 将用户参数放置在 HTTP 请求正文中。这具有三个主要优点:

  • 减少日志记录:由于 POST 请求可能会传输大文件(例如文件上传),因此服务器将所有上传的文件记录为请求的 URL 的一部分并不高效,就像使用通过 GET 请求上传的文件。
  • 更少的编码要求:URL 被设计为共享,这意味着它们需要符合可以转换为字母的字符。 POST 请求将数据放置在可接受二进制数据的正文中。唯一需要编码的字符是用于分隔参数的字符。
  • 可发送更多数据:可以发送更多数据:最大 URL 长度因浏览器 (Chrome/Firefox/IE)、Web 服务器 (IIS、Apache、nginx)、内容而异交付网络(Fastly、Cloudfront、Cloudflare),甚至 URL 缩短器(bit.ly、amzn.to)。一般来说,URL 的长度应保持在 2,000 个字符以下,因此它们无法处理大量数据。

3.1 使用cURL发送POST请求

我们将使用 -X POST 标志来发送 POST 请求。然后,要添加 POST 数据,我们可以使用 -d 标志并在其后添加上述数据,如下所示:

1
d4rk30@linux$ curl -X POST -d 'username=admin&password=admin' http://<SERVER_IP>:<PORT>/

提示:许多登录表单在经过身份验证后会将我们重定向到不同的页面(例如/仪表板.php)。如果我们想使用 cURL 进行重定向,我们可以使用 -L 标志。

3.2 Authenticated Cookies

如果我们成功通过身份验证,我们应该会收到一个 cookie,以便我们的浏览器可以保留我们的身份验证,并且我们不需要每次访问该页面时都登录。我们可以使用 -v 或 -i 标志来查看响应,该响应应包含带有我们经过身份验证的 cookie 的 Set-Cookie Header:

1
d4rk30@linux$ curl -X POST -d 'username=admin&password=admin' http://<SERVER_IP>:<PORT>/ -i

通过经过身份验证的 cookie,我们现在应该能够与 Web 应用程序进行交互,而无需每次都提供我们的凭据。为了测试这一点,我们可以在 cURL 中使用 -b 标志设置上述 cookie,如下所示:

1
d4rk30@linux$ curl -b 'PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1' http://<SERVER_IP>:<PORT>/

正如我们所看到的,我们确实通过了身份验证并进入了搜索功能。也可以将 cookie 指定为Header,如下所示:

1
d4rk30@linux$ curl -H 'Cookie: PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1' http://<SERVER_IP>:<PORT>/

3.3 JSON Data

大部分情况下,POST 请求发送时候都是带有 json 格式的数据,尝试用 cURL 发送一个 json 数据的请求:

1
d4rk30@linux$ curl -X POST -d '{"search":"london"}' -b 'PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1' -H 'Content-Type: application/json' http://<SERVER_IP>:<PORT>/search.php

4. CRUD API

4.1 APIs

API 有多种类型。许多API用于与数据库交互,这样我们就可以在API查询中指定请求的表和请求的行,然后使用HTTP方法执行所需的操作。

4.2 CRUD

正如我们所看到的,我们可以通过此类 API 轻松指定要执行操作的表和行。然后我们可以利用不同的 HTTP 方法对该行执行不同的操作。一般来说,API 对请求的数据库实体执行 4 个主要操作:

操作 HTTP 方法 说明
Create POST 将指定数据添加到数据库表
Read GET 从数据库表中读取指定实体
Update PUT 更新指定数据库表的数据
Delete DELETE 从数据库表中删除指定行

这四个操作主要与众所周知的 CRUD API 相关,但相同的原理也适用于 REST API 和其他几种类型的 API。当然,并非所有 API 都以相同的方式工作,用户访问控制将限制我们可以执行的操作以及我们可以看到的结果。 Web 应用程序简介模块进一步解释了这些概念,因此您可以参考它以获取有关 API 及其用法的更多详细信息。

4.3 Read

与 API 交互时我们要做的第一件事就是读取数据。如前所述,我们可以简单地在 API 后面指定表名(例如 /city ),然后指定我们的搜索词(例如 /london ),如下所示:

1
2
3
d4rk30@linux$ curl http://<SERVER_IP>:<PORT>/api.php/city/london

[{"city_name":"London","country_name":"(UK)"}]

我们看到结果以 JSON 字符串的形式发送。为了将其正确格式化为 JSON 格式,我们可以将输出通过管道传输到 jq 实用程序,该实用程序将对其进行正确格式化。我们还将使用 -s 静默任何不需要的 cURL 输出,如下所示:

1
2
3
4
5
6
7
8
d4rk30@linux$ curl -s http://<SERVER_IP>:<PORT>/api.php/city/london | jq

[
{
"city_name": "London",
"country_name": "(UK)"
}
]

4.4 Create

要添加新条目,我们可以使用 HTTP POST 请求,这与我们在上一节中执行的操作非常相似。我们可以简单地 POST JSON 数据,它将被添加到表中。由于此 API 使用 JSON 数据,我们还将 Content-Type 标头设置为 JSON,如下所示:

1
d4rk30@linux$ curl -X POST http://<SERVER_IP>:<PORT>/api.php/city/ -d '{"city_name":"City", "country_name":"Country"}' -H 'Content-Type: application/json'

现在,我们可以读取我们添加的城市,看看它是否已成功添加:

1
d4rk30@linux$ curl -s http://<SERVER_IP>:<PORT>/api.php/city/City | jq

4.5 Update

现在我们知道如何通过 API 读取和写入条目,让我们开始讨论其他两种 HTTP 方法到目前为止我们还没有使用过: PUT 和 DELETE 。正如本节开头提到的, PUT 用于更新 API 条目并修改其详细信息,而 DELETE 用于删除特定实体。

注意: HTTP PATCH 方法也可用于更新 API 条目而不是 PUT 。准确地说,PATCH 用于部分更新条目(仅修改其部分数据“例如仅 city_name”),而 PUT 用于更新整个条目。我们还可以使用HTTP OPTIONS方法来查看服务器接受两者中的哪一个,然后相应地使用适当的方法。在本节中,我们将重点关注 PUT 方法,尽管它们的用法非常相似。

使用 PUT 与 POST 非常相似,唯一的区别是我们必须指定我们想要的实体的名称在 URL 中进行编辑,否则 API 将不知道要编辑哪个实体。因此,我们所要做的就是在 URL 中指定城市名称,将请求方法更改为 PUT ,并像使用 POST 一样提供 JSON 数据,如下所示:

1
d4rk30@linux$ curl -X PUT http://<SERVER_IP>:<PORT>/api.php/city/london -d '{"city_name":"New_City", "country_name":"Country"}' -H 'Content-Type: application/json'

注意:在某些 API 中,更新操作也可用于创建新条目。基本上,我们会发送数据,如果它不存在,它会创建它。例如,在上面的示例中,即使包含伦敦城市的条目不存在,它也会使用我们传递的详细信息创建一个新条目。然而,在我们的示例中,情况并非如此。尝试更新一个不存在的城市,看看会得到什么。

4.6 DELETE

最后,我们尝试删除一个城市,这就像读取一个城市一样简单。我们只需为 API 指定城市名称并使用 HTTP DELETE 方法,它就会删除该条目,如下所示:

1
d4rk30@linux$ curl -X DELETE http://<SERVER_IP>:<PORT>/api.php/city/New_City