蚊章汇 - Tom Wilson
type: channel
link: https://linuxcn.bwsl.wang/author/1555/
description: Tom Wilson
items: 完善的 API 的 4 个基本特征

完善的 API 的 4 个基本特征
type: item
date: 2021-06-14T23:56:06+08:00
description: 创建一个 API（应用程序接口），我们所要做的远远不止是让它能“正常工作”。如果你正在构建基于 C/S 模型的应用程序，那么你需要一个应用程序接口（API）。API 就是一种非常清晰而又明确的定义，它是一个 进程 process 与另一个进程之间明确定义的边界。Web 应用中我们常见的边界定义就是 REST/JSON API。虽然很多开发者可能主要关注在如何让 API 正常工作（或功能正常），但却还有一些“非功能性”的要求也是需要他们注意的。所有的 API 必须具备 的 4 个非功能性的要求是：安全文档验证测试安全在软件开发中，安全是最基本的要求。对于 API 开发者来说，API 的安全性主要包含以下 4 个方面：HTTPS/SSL 证书跨域资源共享身份认证与 JSON Web 令牌授权与作用域1、HTTPS/SSL 证书Web 应用的黄金标准是使用 SSL 证书的 HTTPS 协议。Let's Encrypt 可以帮你达到这一目的。Let's Encrypt 来自于非营利性的互联网安全研究小组（ISRG），它是一个免费的、自动化的、开放的证书颁发机构。Let's Encrypt 的软件会为你的域（LCTT 译注：包含域名、IP 等信息）生成中央授权证书。而正是这些证书确保了从你的 API 到客户端的数据载荷是点对点加密的。Let's Encrypt 支持证书管理的多种部署方案。我们可以通过查看 文档 来找出最适合自己需要的方案。2、跨域资源共享 跨域资源共享 Cross-origin resource sharing （CORS）是一个针对浏览器的安全策略预检。如果你的 API 服务器与发出请求的客户端不在同一个域中，那么你就要处理 CORS。例如，如果你的服务器运行在 api.domain-a.com 并且接到一个来自 domain-b.com 的客户端的请求，那么 CORS 就会（让浏览器）发送一个 HTTP 预检请求，以便查看你的 API 服务是否会接受来自此客户域的客户端请求。来自 MDN 的定义：“跨域资源共享（CORS）是一种基于 HTTP 头的机制，这种机制允许服务器标记除自身源外的其他任何来源（域、方案或端口）。而对于这些被服务器标识的源，浏览器应该允许我们从它们加载资源。”(MDN文档， CC-BY-SA 2.5)另外，有很多用于 Node.js 的辅助库来 帮助 API 开发者处理 CORS。3、身份认证与 JSON Web 令牌有多种方法可以验证你的 API 中的认证用户，但最好的方法之一是使用 JSON Web 令牌（JWT），而这些令牌使用各种知名的加密库进行签名。当客户端登录时，身份管理服务会向客户端提供一个 JWT。然后，客户端可以使用这个令牌向 API 发出请求，API 收到请求后，从服务器读取公钥或私密信息来验证这个令牌。有一些现有的库，可以帮助我们对令牌进行验证，包括 jsonwebtoken。关于 JWT 的更多信息，以及各种语言中对其的支持库，请查看 JWT.io。import jwt from 'jsonwebtoken' export default function (req, res, next) { // req.headers.authorization Bearer token const token = extractToken(req) jwt.verify(token, SECRET, { algorithms: ['HS256'] }, (err, decoded) => { if (err) { next(err) } req.session = decoded next() }) } 4、授权与作用域认证（或身份验证）很重要，但授权同样很重要。也就是说，经过验证的客户端是否有权限让服务器执行某个请求呢？这就是作用域的价值所在。当身份管理服务器对客户端进行身份认证，且创建 JWT 令牌时，身份管理服务会给当前客户提供一个作用域，这个作用域将会决定当前经过验证的客户的 API 请求能否被服务器执行。这样也就免去了服务器对访问控制列表的一些不必要的查询。作用域是一个文本块（通常以空格分隔），用于描述一个 API 端点的访问能力。一般来说，作用域被分为资源与动作。这种模式对 REST/JSON API 很有效，因为它们有相似的 RESOURCE:ACTION 结构。（例如，ARTICLE:WRITE 或 ARTICLE:READ，其中 ARTICLE 是资源，READ 和 WRITE 是动作）。作用域的划分让我们的 API 能够专注于功能的实现，而不是去考虑各种角色和用户。身份访问管理服务可以将不同的角色和用户分配不同的权限范围，然后再将这些不同的作用域提供给不同的 …