要创建一个API(应用程序编程接口),我们需要做的不仅仅是让它“正常工作”。如果您正在构建基于C/S模型的应用程序,那么您需要一个应用程序编程接口(API)。API是一个非常清晰和定义明确的定义,它是一个进程与另一个进程之间定义明确的边界。我们在Web应用程序中常见的边界定义是REST/JSONAPI。虽然许多开发人员可能主要关心让API工作(或正常运行),但也有需要他们注意的“非功能性”要求。所有API都必须具备的4个非功能性需求是:安全文档验证测试安全在软件开发中,安全是最基本的需求。对于API开发者来说,API安全主要包括以下四个方面:HTTPS/SSL证书跨域资源共享身份认证和JSONWebtoken授权及范围1.HTTPS/SSL证书Web应用的黄金标准是SSL使用HTTPS协议证书。Let'sEncrypt可以帮助您实现这一目标。来自非营利性互联网安全研究小组(ISRG)的Let'sEncrypt是一个免费、自动化和开放的证书颁发机构。Let'sEncrypt的软件会为您的域生成中央授权证书。正是这些证书确保从您的API到客户端的数据负载是端到端加密的。Let'sEncrypt支持证书管理的多种部署场景。我们可以通过查看文档找到最适合我们需求的解决方案。2.跨域资源共享跨域资源共享(CORS)是一种针对浏览器的安全策略预检查。如果您的API服务器与请求客户端不在同一个域中,那么您必须处理CORS。例如,如果您的服务器在api.domain-a.com上运行并收到来自domain-b.com的客户端的请求,CORS将(使浏览器)发送一个HTTP预检请求以查看您的API是否服务将接受来自该客户端域的客户端请求。来自MDN的定义:“跨源资源共享(CORS)是一种基于HTTP标头的机制,它允许服务器标记除自身以外的任何来源(域、方案或端口)。对于服务器识别的那些,浏览器应该允许我们从他们那里加载资源。”(MDN文档,CC-BY-SA2.5)此外,还有许多用于Node.js的帮助程序库可帮助API开发人员处理CORS。3.使用JSONWebTokens进行身份验证有多种方法可以在你的API中对经过身份验证的用户进行身份验证,但最好的方法之一是使用JSONWebTokens(JWT),它使用各种知名的加密库进行签名。当客户端登录时,身份管理服务向客户端提供JWT。然后,客户端可以使用此令牌向API发送请求。API收到请求后,从服务器读取公钥或私钥信息,对token进行验证。有一些现有的库可以帮助我们验证令牌,包括jsonwebtoken。有关JWT以及以各种语言支持它的库的更多信息,请查看JWT.io。importjwtfrom'jsonwebtoken'exportdefaultfunction(req,res,next){//req.headers.authorizationBearertokenconsttoken=extractToken(req)jwt.verify(token,SECRET,{algorithms:['HS256']},(err,decoded)=>{if(err){next(err)}req.session=decodednext()})}4.授权和范围认证(或认证)很重要,但授权也很重要。换句话说,经过身份验证的客户端是否有权让服务器执行请求?这就是范围的价值。当身份管理服务器对客户端进行认证并创建JWTtoken时,身份管理服务会为当前客户端提供一个范围,该范围将决定当前认证客户端的API请求是否可以被服务器执行。这也使服务器免于对访问控制列表进行不必要的查询。范围是描述API端点可访问性的文本块(通常由空格分隔)。通常,范围分为资源和操作。此模式适用于REST/JSONAPI,因为它们具有类似的RESOURCE:ACTION结构。(例如,ARTICLE:WRITE或ARTICLE:READ,其中ARTICLE是资源,READ和WRITE是操作)。范围的划分让我们的API可以专注于功能的实现,而不是考虑各种角色和用户。身份访问管理服务可以为不同的角色和用户分配不同的权限范围,然后在不同的JWT认证中将这些不同的范围提供给客户。总结当我们开发和部署API时,安全性应该始终是最重要的要求之一。安全虽然是一个宽泛的话题,但是如果能解决以上四个方面,那么你的API在生产环境中的表现会更好。还有什么比没有文档更糟糕的呢?过时的文档。开发人员对文档真的是又爱又恨。尽管如此,文档仍然是定义明确的API的关键部分。开发人员需要从文档中了解如何使用这些API,而您创建的文档对于开发人员如何更好地使用API也起着巨大的作用。创建API文档需要关注以下三个方面:开发者入门文档(Readme/BasicIntroduction)技术参考(Specifications/Instructions)HowtoUse(入门及其他指南)1.GettingStartedDocumentsWhenbuildingAPIservices,你有些东西需要弄清楚,比如:这个API是做什么的?如何搭建开发环境?如何测试服务?如何提交问题?如何部署?通常我们可以通过README文件来回答上述问题,README文件通常放在你的代码库中,为开发者提供最基本的起点和使用你的项目的说明。自述文件应包含:API的描述技术参考和指南的链接作为开发人员如何设置项目如何测试项目如何部署项目您不必解释每个方面,但提供足够的信息以便开发人员在熟悉您的项目后可以进一步深入研究。2.技术参考在REST/JSONAPI中,每个特定的端点对应一个特定的功能,需要特定的文档,这一点非常重要。该文档定义了API的描述、其输入和可能的输出,并为各种客户端提供了使用示例。OpenAPI是创建REST/JSON文档的标准,它会指导您了解编写API文档所需的各种细节。OpenAPI还可以为您的API生成演示文档。3.如何使用对于API用户来说,技术描述是不够的。他们还需要知道在一些特定的情况和场景下如何使用这些API,大多数潜在用户可能希望你的API能够解决他们遇到的问题。向用户介绍您的API的一个好方法是使用“入门”页面。“入门”页面通过一个简单的用例引导用户,让他们快速了解您的API可以为他们做什么。总结文档是任何开发良好的API的重要组成部分。当你创建一个文档时,你需要在API文档中关注三个方面:如何上手、技术参考、如何快速上手,这样你的API才算是一个完整的API。验证API开发过程中经常被忽视的一点是验证。这是一个验证来自外部来源的输入的过程。这些来源可以是客户端发送过来的JSON数据,也可以是你请求别人的服务收到的响应数据。我们不仅要检查这些数据的类型,还要确保数据确实是我们想要的数据,这样可以排除很多潜在的问题。了解您的边界以及您可以控制和不能控制的内容是API数据验证的一个重要方面。最好的策略是在进入数据逻辑处理之前,在你可以控制的边界边缘验证数据。当客户端向您的API发送数据时,您需要在对数据进行任何操作之前应用您的验证,例如:确保电子邮件是真实的电子邮件地址,日期数据具有正确的格式,并且字符串符合长度要求.这个简单的检查可以为您的应用程序增加安全性和一致性。此外,当您从数据库或缓存等服务接收数据时,您需要重新验证数据以确保返回的结果与您的数据检查相匹配。你可以手写这些验证逻辑,当然你也可以使用像Lodash或者Ramda这样的函数库,这些函数库对于一些小的数据对象非常有用。像Joi、Yup或Zod这样的验证库会工作得更好,因为它们包含一些常用的验证方法,可以节省您的时间和精力。除其他外,它们创建了更具可读性的模式。如果您需要查看与语言无关的内容,请查看JSONSchema。摘要数据验证虽然不显眼和突出(LCTT译注:与API等几个方面的功能实现相比),但可以为你节省很多时间。如果未完成验证,这些时间可能会花在故障排除和编写数据迁移脚本上。真的不要相信您的客户端会向您发送干净的数据,也不要让无效数据泄漏到您的业务逻辑或持久数据存储中。花一些时间来验证您的API收到的数据和请求的响应数据。虽然前期你可能会感到一些沮丧和不适,但总比后期花很多时间在各种数据紧缩控制和失败上要好。更容易排除等。测试测试是软件开发中的最佳实践,它应该是最重要的非功能性需求。确定测试策略对任何项目(包括API)来说都是一项挑战,因为您在整个过程中都受到限制,无法相应地制定测试策略。集成测试集成测试是测试API的最有效方法之一。在集成测试模式中,开发团队创建了一套测试,涵盖应用程序流程的某个部分,从一点到另一点。一个好的集成测试过程包括测试API的入口点和模拟从请求到服务器的响应。搞定这两点,你就覆盖了整个逻辑,从开始的API请求,到模拟服务器的响应,再到API返回数据。虽然使用了mocking,但是这种方式可以让我们专注于代码的逻辑层,而不必依赖后端服务和表现逻辑来进行测试。没有依赖关系的测试更可靠,更容易自动化,也更容易进入持续集成管道。在集成测试的实现中,我会使用Tape、Test-server和Fetch-mock。这些库允许我们进行从API请求到数据响应的隔离测试,并使用Fetch-mock将出站请求捕获到持久层。结论虽然其他类型的测试和类型检查也适用于API,但集成测试在流程效率、构建和管理时间方面具有更大的优势。使用像Fetch-mock这样的工具可以在服务边界提供一个干净的模拟场景。专注于基础无论您是在设计和构建应用程序还是API,请确保包含上述四个要素。它们不是我们需要考虑的唯一非功能性需求,其他需求还包括应用程序监控、日志记录和API管理等。即便如此,安全性、文档、验证和测试这四个基本要素对于构建良好的API来说是至关重要的任何用例。
