RESTful API设计之道-RESTful API介绍及使用方法

概述:API 是“Application Program Interface”的首字母缩写。WEB API 可用于多种应用程序,并充当两个应用程序之间的一种中介。如果要创建网站、单页应用程序 (SPA) 或移动应用程序,或者需要与服务器端的服务进行通信,或者即使一个应用程序需要与另一个应用程序(例如:客户端到服务器)进行通信,则可以使用 API。还可以将 API 与人工智能、机器学习、云、微服务、大数据和许多其他技术结合使用。为了设计一个好的API,可以遵循一些原则。在本文中,我将解释其中的一些原则。HTTP 协议在开始讨论REST本身之前,我将解释一下HTTP协议。HTTP 协议用于通过请求和响应

API 是“Application Program Interface”的首字母缩写。WEB API 可用于多种应用程序,并充当两个应用程序之间的一种中介。如果要创建网站、单页应用程序 (SPA) 或移动应用程序,或者需要与服务器端的服务进行通信,或者即使一个应用程序需要与另一个应用程序(例如:客户端到服务器)进行通信,则可以使用 API。还可以将 API 与人工智能、机器学习、云、微服务、大数据和许多其他技术结合使用。为了设计一个好的API,可以遵循一些原则。在本文中,我将解释其中的一些原则。

HTTP 协议

在开始讨论REST本身之前,我将解释一下HTTP协议。HTTP 协议用于通过请求和响应与服务器进行通信。例如,在 WEB 应用程序的情况下,UI 将在后端向服务发出请求,服务将处理此请求并返回响应。这是HTTP工作原理的一个例子:

图片

HTTP 是一种允许获取资源(例如 HTML 文档)的协议。它是 Web 上任何数据交换的基础,它是一种客户端-服务器协议,这意味着请求由接收方(通常是 Web 浏览器)发起。客户端和服务器通过交换单个消息(而不是数据流)进行通信。客户端(通常是 Web 浏览器)发送的消息称为请求,服务器作为应答发送的消息称为响应。

HTTP 请求包含三个部分:

  • 动词:这是动作本身,例如 Get、Post、Put 等

  • 标头:包含有关请求的信息;可以添加一些有用的信息,例如 cookie、JWT 令牌等。

  • 内容:添加需要写入的信息的位置。例如,当插入新客户时,客户数据将出现在请求消息中。

HTTP 响应(文本中的一段数据)包含三个部分:

  • 状态代码 — 每个状态代码都表示某种含义,例如:200 表示“确定”,201 表示“已创建”,404 表示“错误请求”,依此类推

  • 标题 — 可以包含一些有用的信息

  • **内容 —**服务器发回的任何内容。例如,当请求客户列表时,此列表将出现在响应消息中。

HTTP 谓词

HTTP 定义了一组请求方法,用于指示要对给定资源执行的所需操作。虽然它们也可以是名词,但这些请求方法有时被称为 HTTP 动词。

基本动词是:

  • GET — 请求特定资源的表示形式。它仅用于返回数据。

  • POST — 用于将实体提交到特定资源。它用于创建新资源。

  • PUT — 用于替换资源的所有属性。它用于更新资源**。**

  • PATCH — 用于应用部分修改(当不需要更新所有资源,而只更新部分资源时,会使用此修改)。

  • DELETE — 用于删除资源。

还有其他动词,但这些是最常用的动词。使用它们,可以执行 CRUD(创建、更新、读取、删除)操作。

状态码

在 API 的响应中返回状态代码。这是一个代表成功或失败的数字。当客户端向 API 发出请求时,它将在发出请求后从服务器返回状态代码。一些状态代码是:

  • 200 — 正常:此状态表示请求成功。

  • 201 — 已创建:此状态表示请求已成功,因此已创建新资源。这通常在 POST 请求后返回。

  • 204 — 无内容:当我们不想返回任何内容时,我们可以返回此状态。

  • 400 — BadRequest:这是错误的通用状态。这意味着由于语法无效,服务器无法理解请求。

  • 401 — 未经授权:此状态表示客户端未通过身份验证,他应进行身份验证以执行请求。

  • 403 — 禁止执行:此状态表示客户端已通过身份验证,但他无权执行他尝试执行的操作。与 401 不同,服务器知道客户端的身份。

  • 404 — 未找到:此状态表示服务器找不到请求的资源。

  • 500 — 内部服务器错误:这是来自 REST API 的通用答案,这意味着服务器遇到了不知道如何处理的情况。

  • 503 — 服务不可用:此状态表示服务器尚未准备好处理请求。

如果您想了解更多关于其他代码的信息,可以单击此处阅读 Mozilla 文档。

REST — 再表示状态传输

术语“REST”是“Representational State Transfer”的首字母缩写。它是分布式超媒体系统的一种架构风格,由Roy Fielding于2000年在其著名的论文中首次提出(您可以单击此处阅读此文档)。

REST,即 REpresentational State Transfer,是一种架构风格,用于在 Web 上的计算机系统之间提供标准,使系统更容易相互通信。

REST 有六个指导约束,如果需要将接口称为 RESTfull,则必须满足这些约束。这些原则是:

  • 客户端-服务器 — 关注点分离是客户端-服务器约束背后的原则。通过将用户界面问题与数据存储问题分开,我们提高了用户界面在多个平台上的可移植性,并通过简化服务器组件来提高可扩展性。然而,对 Web 来说,也许最重要的一点是,这种分离允许组件独立发展,从而支持多个组织域的 Internet 规模需求。

  • 无状态 — 通信本质上必须是无状态的。从客户端到服务器的每个请求都必须包含理解请求所需的所有信息,并且不能利用服务器上的任何存储上下文。因此,会话状态完全保留在客户端上。

  • 可缓存 — 缓存约束要求对请求的响应中的数据被隐式或显式标记为可缓存或不可缓存。如果响应是可缓存的,则客户端缓存有权在以后的等效请求中重用该响应数据。您发出的所有请求都应支持可缓存性。

  • 统一接口 — 通过将通用性软件工程原则应用于组件接口,简化了整个系统架构,提高了交互的可见性。实现与它们提供的服务分离,这鼓励了独立的可进化性。

  • 分层系统 — 分层系统样式允许架构由分层层组成,通过约束组件行为,使每个组件无法“看到”它们与之交互的直接层之外。

  • 按需代码(可选) — REST 允许通过下载和执行小程序或脚本形式的代码来扩展客户端功能。这通过减少需要预先实现的功能数量来简化客户端。允许在部署后下载功能可提高系统可扩展性。但是,它也会降低可见性,因此只是 REST 中的可选约束。

**REST(**Representational State Transfer)是指一组软件架构设计约束,它们带来了高效、可靠和可扩展的分布式系统。

REST的基本思想是,资源(例如文档)是通过公认的、与语言无关的、可靠的标准化客户端/服务器交互来传输的。当服务遵守这些约束时,它们被视为 RESTful。

通常,HTTP API 有时通俗地称为 RESTful API、RESTful 服务或 REST 服务,尽管它们不一定遵守所有 REST 约束。初学者可以假设 REST API 是指可以使用标准 Web 库和工具调用的 HTTP 服务。

REST API 是使用 HTTP 请求获取或操作数据的应用程序接口 (API)。在REST体系结构中,客户端发送请求以获取或修改资源,服务器发送对这些请求的响应。要执行这些请求,请使用 HTTP 谓词。

术语“Restful”是指使用 REST 的实用方法,这意味着 Web API 应用 REST 原则。不完全 RESTful 的 API 并不少见,原因是一直应用所有原则有点困难,所以分析每种情况总是好的,不要受到太大的限制。确保您正在为应用程序本身构建最佳内容。

资源

REST中信息的关键抽象是一种资源。任何可以命名的信息都可以是资源:文档或图像、时态服务、其他资源的集合、非虚拟对象(例如人)等。REST 使用资源标识符来标识组件之间交互中涉及的特定资源。

每个 URI 都指向一个资源,资源表示表示系统中对象的事物,例如:产品、客户、书籍等。还可以将资源视为域模型/实体。它们是您想要获取、插入、更新和删除的内容。

任何 RESTful API 的基本概念都是资源。资源是具有类型、关联数据、与其他资源的关系以及一组对其进行操作的方法的对象。它类似于面向对象编程语言中的对象实例,但重要的区别是只为资源定义了几个标准方法(对应于标准的 HTTP GET、POST、PUT 和 DELETE 方法),而对象实例通常具有许多方法。

RESTfull API 示例

在本节中,我将展示一个 REST API 示例,以及在考虑 RESTfull 时考虑的一些原则。在此示例中,让我们考虑一个需要处理书籍的场景。我们将有一个端点来创建、获取所有书籍、获取一本书、更新和删除一本书。

URI 中的约定

在 REST 中,URI 是资源的路径。为了演示一些示例,我在本地运行一个 Web API。在本例中,基本 URI 为:。在带有地址的基本 URI 之后,指定对象/资源,在本例中是书籍,因此 URI 是这样的: 。https://localhost:5001/https://localhost:5001/books

想象一下,您有一个 CRUD 操作来处理书籍。以下是它使用 RESTful 约定的方式:

GET /api/books         (to get all the books)  
GET /api/books/1 (to get a single book searching by id 1)
PUT /api/books/1 (to update a book with id 1)
DELETE /api/books/1 (to delete a book with id 1)
POST /api/books (to create a book)

请注意,每个端点都包含一个 HTTP 谓词,后跟 “” 和 “”。如果我们使用“客户”而不是“预订”,那就是:“”。这是一个约定。此外,对于每个操作,它都使用特定的 HTTP VERB(例如:GET、POST、DELETE 或其他)。/api/books/api/customers/

当我们使用 RESTful API 时**,名词是可取**的。因此,在 API 的设计中,我们应该使用名词,而不是使用动词。例如,它不是像 和 ,而是: ,HTTP Verb 将指定哪种操作。通常,它也将是复数形式(而不是 ),除非在处理单个项目的情况下,例如,在将返回一本书的情况下。/getBooks/deleteBook/booksbooksbookbook/title

在 URI 中,还应使用一些唯一标识符,因为每个 URI 都必须指向特定资源。在上面的端点列表中,书籍的 id 正在某些操作(Get、Put 和 Delete)中使用,但不强制使用 id,也可能是其他一些唯一标识符。

还可以对非资源属性使用查询字符串。它通常用作格式化、排序、搜索等元素。它们是查询字符串,因为它们不是 URI 本身的一部分,它们与这些 URI 或这些资源的可选参数有关。例如,我们可以有类似的东西:或,或其他。/books?sort=title/books?page=2

为了演示 API 请求,我使用 Swagger 在本地运行一个 API(如果您使用的是 .NET 5,则在创建 Web API 项目时会自动配置 Swagger;如果您想了解有关 Swagger 的更多信息,可以单击此处访问 Swagger 的网站)。也可以使用 Postman 等工具向 API 发出请求。这是 Swagger (OpenAPI) 的示例:

图片

图片

图片

图片

图片

特定请求的效果应取决于资源是集合还是单个项。下表总结了使用电子商务示例的大多数 RESTful 实现所采用的常见约定。并非所有这些请求都可能实现 — 这取决于具体方案:

图片

https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design

幂等 API

REST API 必须是幂等的。幂等意味着“可以在不改变结果的情况下多次应用的操作”。这意味着 API 执行的操作必须始终导致相同的副作用。

在 GET、PUT、PATCH 和 DELETE 的情况下,它应该始终执行相同的操作。GET 应始终返回相同的数据(当然,除非系统中的某些内容发生了变化),PUT 和 PATCH 应始终在必要时执行相同的更改,而 DELETE 应删除项目或返回错误。所以,例如。如果您多次执行 PUT,它不应该在第二个或第三个请求中失败,因为没有更改任何内容,但它应该始终有效。幂等的一个例外是 POST,它从来都不是幂等的。每次对 API 进行 POST 时,它始终会返回一个新的对象/资源。

因此,如果您多次发出相同的请求并不重要,结果必须始终相同,当然,除非某些数据在两次调用之间被另一个请求更改。

缓存

当我们考虑 RESTfull API 时,缓存是另一个要求。当然,并非所有 API 都需要缓存,但为了纵向扩展,缓存是您应该考虑的事情。

“如果不能显著提高性能,缓存将毫无用处。HTTP/1.1 中缓存的目标是在许多情况下消除发送请求的需要,并在许多其他情况下消除发送完整响应的需要。(HTTP标准)

缓存是一种存储给定资源副本并在请求时返回的技术。当 Web 缓存的存储中有请求的资源时,它会截获该请求并返回其副本,而不是从原始服务器重新下载。这实现了几个目标:它减轻了服务器的负载,不需要为所有客户端本身提供服务,并且通过更接近客户端来提高性能,即将资源传输回所需的时间更少。对于网站来说,它是实现高性能的主要组成部分。另一方面,它必须正确配置,因为并非所有资源都永远保持相同:重要的是只缓存资源,直到它发生变化,而不是更长时间。

可以有服务器端缓存(这很好),这意味着例如,如果两个或多个客户端请求同一本书,则将其缓存在服务器上以便更快地返回。但是 REST API 中的缓存意味着使用 HTTP 进行缓存机制。例如,当您发出 HTTP 请求以请求某些内容并包含提供数据的最后一个版本时,响应应为 304 — 未修改。因此,在这种情况下,客户端将询问服务器是否有最新版本,而服务器不必找到它,然后将其发回以便您可以进行比较。

通过重用以前获取的资源,可以显著提高网站和应用程序的性能。Web 缓存可减少延迟和网络流量,从而减少显示资源表示形式所需的时间。通过使用 HTTP 缓存,网站的响应速度更快。

如果匹配

HTTP 请求标头使请求成为条件请求。对于 和 方法,仅当请求的资源与列出的资源之一匹配时,服务器才会发回请求的资源。对于和其他不安全的方法,在这种情况下,它只会上传资源。If-MatchGETHEADETagsPUT

执行 HTTP 缓存的另一种方法是在请求上使用名为 If-Match 的标头。因此,在这种情况下,它将被发送一个标识符来指定它在服务器上的版本,然后当客户端尝试更新(PUT)时,例如,以一种并发的方式,它将检查客户端发送的版本是否与服务器上的版本相同,如果为正,则将应用更改, 否则,它将返回 412 — Precondition Failed,因为标头成为前提条件。以下是如何使用 If-Match 的两个示例:

If-Match: "bfc13a64729c4290ef5b2c2730249c88ca92d82d"  

If-Match: "67ab43", "54ed21", "7892dd"

实体标记 (ETag)

处理此缓存的一个好方法是使用实体标记 (Etags)。它支持强缓存和周缓存。强缓存用于支持将存在很长时间的内容,例如,如果您需要缓存某些内容三周。周缓存适用于生存时间非常短的内容。

HTTP 响应标头是资源特定版本的标识符。它使缓存更有效率并节省带宽,因为如果内容未更改,Web 服务器无需重新发送完整响应。此外,etag 有助于防止资源的同时更新相互覆盖(“空中碰撞”)。ETag

这些 ETag 将在响应中返回一些唯一标识符,该标识符表示服务器上资源的版本,并将在标头中返回。例如:

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

如果需要返回一周类型,则在 ETAG 中先使用相同的格式,这样就可以向开发人员表明此缓存支持的强度:W/

ETag: W/"33a64df551425fcc55e4d42a148795d9f25f89d4"

此唯一标识符将在标头中返回,也可用于跟踪目的。

避免空中碰撞

使用 ETag 和 If-Match 可以方便地检测空中编辑冲突。例如,当某些内容更新时,将在响应的 Etag 标头中添加唯一标识符:

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

当有人更新时,请求将包含包含要检查的值的标头:If-MatchETag

If-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

如果唯一标识符不匹配,则表示资源已在两者之间编辑,并且将引发 412 — Precondition Failed 错误。

支持并发 — RESTfull

支持并发的一种方法是使用生成 ETag 的组件。这是它的工作原理:

图片

出于演示目的,让我们考虑一个场景,其中我们有两个客户端:客户端 1 和客户端 2。这是您在上图中看到的:

1 — 客户端 1 发送请求以获取 Book,并返回 ETag“123456789”。

2 — 在此期间,客户 2 还:

2.1 – 发送请求以获取书籍,并返回 ETag“123456789”

2.2 — 然后客户端 2 发送一个 PUT 请求来更新在 If-Match 标头中传递 ETag“123456789”的书籍,然后 API 检查此标头,与为该响应保存的 ETag 进行比较,如果它们匹配(在本例中,它们匹配),则将应用更新,此时将为响应生成新的 ETag, ETag “987654321”。

3 — 之后,客户端 1 发送带有包含“1234567989”的 If-Match 标头的更新,这是客户端 1 当前拥有的 ETag,现在将发生的情况是它将到达 API,并且 API 将检查此 ETag 是否与该资源的最新 ETag 不匹配,因此 API 将返回 412 前提条件失败, 并且不会应用来自客户 1 的更新,因为他正在处理该书的旧版本(他应该首先获得该书的新副本以进行处理)。

缓存未更改的资源

标头的另一个典型用途是缓存未更改的资源。如果用户再次访问给定的 URL(具有集),并且该 URL 已_过时_(太旧而无法被视为可用),则客户端将在标头字段中发送其值:ETagETagETagIf-None-Match

If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

服务器将客户端的 (发送方式 ) 与其当前版本的资源进行比较,如果两个值都匹配(即资源未更改),则服务器将发回 304 — 未修改状态,不带正文,该状态告诉客户端响应的缓存版本仍然可以使用(全新)。ETagIf-None-MatchETag

提示:使用 Postman 时,默认情况下,配置设置为发送无缓存标头。因此,为了测试缓存,可以在设置中禁用此选项。

对 API 进行版本控制

对 API 进行版本控制非常重要,以防止对客户端进行重大更改。例如,假设一个或多个客户端正在使用您的 API,并且您在 API 中进行了一些更改,这些更改会影响数据的结构方式,并且一旦发布了此新更改,客户端将无法再使用 API,除非他们也更新了。因此,为了避免这种情况,我们可以使用版本控制。

例如,API 的第一个版本将是 v1.0,第二个版本将是 v2.0。当版本 2 发布时,仍然可以在一段时间内使用版本 1,您可以通知您的客户,说在一段时间内版本 1 将不再可用,他们需要更新到版本 2。在此时间段之后,您可以停用 API 的版本 1。这样,当您更新 API 时,即使您更新了可能导致中断更改的内容,这也不会直接影响已经使用它的人,并且您将给您的客户一些时间,以便他们使用最新版本的 API 更新他们的应用程序。

如果您有很多客户端,并且其中一个客户端需要尽快使用特定功能,这也很方便,但此功能可能会导致一些中断更改。在这种情况下,您可以创建一个新版本,并且需要此新功能的客户端已经可以使用它,其他客户端将有一些时间进行更新。

重大更改应始终导致 API 或内容响应类型的主版本号发生更改。重大更改包括:

  • 更改一个或多个呼叫的响应数据格式

  • 请求或响应类型的更改(即将整数更改为浮点数)

  • 删除 API 的任何部分

如果 API 仅由您自己的团队和您自己的应用程序使用,那么为 API 创建版本控制可能太过分了,但是在 API 由内部或外部客户使用的情况下,对 API 进行版本控制非常重要。

对 API 进行版本控制的策略

REST 不提供任何特定的版本控制指南,但可以使用的一些策略包括:

  • 使用 URI 中的 API 版本进行版本控制

  • 使用查询字符串进行版本控制

  • 使用自定义请求标头进行版本控制

  • 使用 Accept 标头进行版本控制

  • 使用内容类型进行版本控制

使用 URI 中的 API 版本进行版本控制

对 API 进行版本控制的一种策略是在 URI 路径中包含版本。这是最常用的方法。例如,如果我们的 API 上有两个版本,则版本 2 的 URI 可能如下所示:

http://api.example.com/v1

http://api.example.com// or using the scenario from the previous example:GET /api/v2/books  
GET /api/v2/books/1
PUT /api/v2/books/1
DELETE /api/v2/books/1
POST /api/v2/books

这种版本控制方式的好处是,客户端很清楚哪个是 API 的版本。缺点是每次版本更改时,都需要更改 URI。

使用查询字符串进行版本控制

另一种策略是使用查询字符串进行版本控制,该字符串将请求特定版本的 API。例如:

http://api.example.com?v=2// or using the

scenario from the previous example:GET /api/books?v=2  
GET /api/books/1?v=2
PUT /api/books/1?v=2
DELETE /api/books/1?v=2
POST /api/books?v=2

这种版本控制方式的好处是,当未指定版本时,可以使用默认版本的 API。不利的一点是,客户端很容易错过 API 的版本。

使用自定义请求标头进行版本控制

另一种版本控制策略是使用自定义请求标头进行版本控制。在这种情况下,API 的版本将位于标头中。例如:

GET /api/books HTTP/1.1  
Host: localhost:5001
Content-Type: application/json
X-Version: 2// or:Accept-version: v1
Accept-version: v2

这种版本控制方式的好处是,这种方法将版本控制与 API 的其余部分分开,因此编写 API 的人不一定需要更改 API 的版本,只需要更新标头中的版本即可。不利的一点是,开发人员处理请求中的标头有点复杂(必须知道如何添加和拦截调用,以便将这些标头添加到其客户端代码中)。

使用 Accept 标头进行版本控制

另一种版本控制策略是使用 Accept Header 进行版本控制。在此方法中,您将使用 accept 标头本身来请求 API 的特定版本,而不是创建自定义标头。例如:

GET /api/books HTTP/1.1  
Host: localhost:5001
Content-Type: application/json
Accept: application/json;version=2

这种版本控制方式的好处是,无需创建自己的自定义标头。缺点是,不像在 URI 中使用查询字符串或版本那样清楚,并且还需要更高的使用复杂性。

使用内容类型进行版本控制

另一种版本控制策略是使用内容类型(或 Accept 标头)进行版本控制。这是最复杂的实现方法,但可能非常有用。在这种方法中,应用程序的每个部分都可以处于特定版本中。下面是一个示例:

GET /api/books HTTP/1.1  
Host: localhost:5001
Content-Type: application/vnd.applicationname.v1+json
Accept: application/vnd.applicationname.v1+json

这种版本控制方式的好处是可以对有效负载(API 中的有效负载是使用 HTTP 中的 GET 方法发送的实际数据包)以及 API 调用本身进行版本控制。缺点是创建和维护更加复杂。

提示: 使用 ASP.NET Core 时,可以使用名为 的库来对 API 进行版本控制。此外,可用于文档的软件包也利用了版本控制。Microsoft.AspNetCore.Mvc.VersioningMicrosoft.AspNetCore.Mvc.Versioning.ApiExplorer

哈特奥阿斯

HATEOAS 代表 Hypermedia as the Engine of Application State,是 RESTful API 设计中的一项基本原则,它增强了 API 的可发现性和可导航性。它通过为客户端提供动态浏览 API 的机制来增强 RESTful API 的可用性和适应性,并在创建自我描述和动态导航的 API 方面发挥关键作用。

HATEOAS 是一个约束,它需要 RESTful API 在响应中提供超媒体链接,以指导客户端在应用程序的任何给定状态下可以执行哪些操作。简单来说,API 不仅告诉客户端请求的资源,还提供指向相关资源和下一步可以执行的操作的链接。

例如,假设客户端请求有关订单的信息,在这种情况下,服务器不仅应检索订单详细信息,还应检索与此订单相关的相关资源的链接。在下面的 JSON 中,有一个响应示例:

{  
"orderId": "123",
"totalAmount": 80.00,
"status": "Shipped",
"customer": {
"customerId": "456",
"name": "Customer Test"
},
"_links": {
"self": { "href": "/api/orders/123" },
"customer": { "href": "/api/customers/456" },
"shipping": { "href": "/api/orders/123/shipping" },
"cancel": { "href": "/api/orders/123/cancel" }
}
}

可以想象,实现 HATEOAS 需要额外的努力,但通过在 API 响应中提供指向相关资源和操作的链接,使 API 更易于使用,从而带来可发现性等好处,因为客户端将知道哪些是下一个可能的可用操作。

保护 API

在以下情况下,您应始终考虑保护 API:

  • 该 API 将使用私人或个性化数据

  • API 将发送敏感数据访问网络

  • API 将使用任何类型的凭据

  • 该 API 将尝试防止过度使用您的服务器

身份验证与授权

简单来说,身份验证就是“你是谁”。身份验证是关于用于确定您的身份的信息,这可能包括用户名和密码或声明等凭据,服务器可以使用此信息来识别您并确保您与您所说的人完全一样。授权是“您可以做什么”,基于身份验证信息,基于身份本身。授权与有关权限、角色、权限的规则有关。

API 的身份验证类型

保护 API 的最常见方法是:

  • 饼干 — 使用cookie既简单又常见,但不太安全。根据您需要的安全级别,cookie 可能是一个不错的选择,但如果您需要更安全的东西,请使用另一种方法。HTTP cookie(Web Cookie、浏览器 Cookie)是服务器发送到用户 Web 浏览器的一小段数据。浏览器可以存储它,并将其与以后的请求一起发送回同一服务器。通常,它用于判断两个请求是否来自同一浏览器,例如,保持用户登录状态。它记住无状态 HTTP 协议的有状态信息。

  • 基本身份验证 — 这也被大量使用,并且易于实现。基本身份验证允许您在查询字符串或标头中传递信息,以及要在服务器上验证的凭据。这也不是那么安全,因为可能会泄露用户的用户名和密码。凭据将在每个请求时发送,有人可以拦截并获取它们。

  • 基于令牌的身份验证 — 这是最常用的,并且具有安全性和简单性的组合。这些令牌有一个标准,通常有中间件支持在大多数平台上创建和验证这些令牌。

  • OAuth — OAuth 有几个标准,它用于允许受信任的第三方识别用户。这样,使用 OAuth 的应用程序永远不会获得凭据。因此,例如,如果您想登录,则可以使用您的Gmail或Microsoft帐户,而不是通知用户名和密码。

令牌身份验证

代币有很多种,其中最常见和最常用的是 JWT 代币。使用这种方法,令牌将在请求的标头中发送,如下所示:

Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

它是这样工作的:客户端将使用他的凭据(例如用户名和密码)向服务器发送请求,服务器将验证此身份验证并返回一个令牌,该令牌是一系列字符。客户端不需要解码此令牌,它只会使用它来发送请求。例如,在 SPA 应用程序中,浏览器将存储此令牌(在移动应用程序中,您可以将其存储在应用程序的缓存中),并且每次客户端请求某些内容时,该令牌都将在请求的标头中发送。然后,服务器将读取此令牌,并验证用户是否有权执行该操作,并将返回响应:

图片

智威汤逊代币

JSON Web 令牌 (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且独立的方式,用于将信息作为 JSON 对象在各方之间安全地传输。此信息可以验证和信任,因为它是数字签名的。可以使用密钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对对对 JWT 进行签名。

JWT 令牌可以包含:

  • 有关用户的信息

  • 对其所拥有的权利的主张

  • 验证签名

  • 其他资讯

要了解令牌的结构,并进行一些测试,您可以使用网站 https://jwt.io/。在下图中,有一个 JWT 令牌的示例:

图片

在这张图片的左侧,有 JWT 代币本身。在右侧,有与此令牌相关的信息。

令牌的红色部分是关于标题的。在标头上,有关于此令牌上使用哪种加密算法(在本例中为“HS256”)以及此令牌是哪种令牌(在此示例中是 JWT 令牌,但存在多种类型的令牌)的信息。

令牌的紫色部分是关于这个令牌的数据。在图片的右侧,在“有效载荷”中,有属性“sub”、“name”和“iat”,这些信息使用算法HS256在此令牌上加密。

令牌的蓝色部分是关于签名的,它使用加密密钥。此密钥是应用程序中的密钥。使用此密钥,可以加密或解密令牌。

Extra: SOAP — 简单对象访问协议

在REST之前,另一种非常常用的模式是SOAP。REST和SOAP的主要区别在于,REST使用HTTP传输数据,但也使用文本来传输数据(数据通过文本发送,并通过文本接收),这就是为什么REST非常轻巧的原因。SOAP也使用HTTP,但基于XML,并且包含的信息比REST多得多。这使得信息更加沉重。在某些情况下,SOAP仍在使用,但总的来说,REST的使用要多得多。

如今,REST API在许多应用程序中都非常广泛,它轻巧,快速且运行良好。遵循本文中提到的原则可以让你在 API 中有一个良好的设计,但不要太局限于此,始终考虑你的应用程序真正需要什么,并利用对你的应用程序有益的原则。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值