这个问题涉及的范围非常大,我怀疑任何单一的答案都可以详细说明问题。我能做的就是根据我所犯的错误提供一些起点。
在您自己的 API 之上构建
不要将 API 功能添加到现有系统中。这样做会:
- 导致额外的测试负载(您必须独立测试您的应用程序和 API)
- 导致整体维护成本增加
- 导致 API 质量低于您想要提供的质量
您的总体目标应该是首先构建 API,然后在您自己的 API 之上构建您的应用程序。这样做有以下好处:
- API 的测试是在测试您的应用程序时固有地执行的
- 您不会“忘记”添加任何必需的 API 方法
您的应用程序和您的应用程序逻辑(API)将在逻辑上分开——就等式的每一边的作用和负责的内容而言,它们之间将有一个明确的分离。这将有助于指导发展。这也将允许您在需要时非常轻松地将应用程序和 API 放在不同的机器上。
使用自己的 API 是非常重要的一点。您的 API 的设计最初将是次优的,只有通过自己使用它,您才能使其以高效的方式向人们提供实际需要的功能。
您最终会得到一个大致如下所示的系统:
------------- -------------
| | | |
| Your APP | <= HTTP communication => | Your API |
| | | |
------------- -------------
这突出了一些进一步的好处:您可以用任何其他应用程序替换“您的应用程序”,允许您的客户创建应用程序以最适合他们的方式处理事情。您还可以在现有 API 之上创建应用程序的新版本 - 迁移到公共网站的新版本会容易得多。
设计您的 URL:映射到类和方法
选择合理的 URL 与选择合理的类和方法名称一样是一个问题。从类及其方法派生 URL 是一种很好的方法。如果 URL 和类/方法之间没有明显的相关性,从长远来看,您会发现事情更难维护。
我个人更喜欢通过以下方式将 URL 关联到类和方法:
示例:
您的 API 的 URL 是https://api.camerareadyart.com。
你有一个image
对象toColour()
和toBlackAndWhite()
方法。
这可能映射到:
https://api.camerareadyart.com/image/toColour/
https://api.camerareadyart.com/image/toBlackAndWhite/
同样对于位图到矢量的转换:
https://api.camerareadyart.com/bitmap/toVector/
设计响应
当有人从您的某个 URL 获取数据或向其发布数据时,会发生什么?错误如何处理,异常如何处理?响应采取什么形式?
我不能告诉你在这里做什么。就我个人而言,我更喜欢将事物尽可能地映射到 HTTP,然后仅在需要时才超出此范围。
例如,如果传入的请求被接受并被处理但在内部遇到错误,我将发出 500 状态响应。同样,如果给定的 API 方法需要尚未提供的身份验证,我可能会发出 403。利用现有的 HTTP 功能可以防止您重新发明某些东西。
使用 HTTP 的现有方面
以及明智地使用 HTTP 状态代码,在推出自己的解决方案之前,请确保四处寻找一种仅用于执行某些操作的 HTTP 方法。
希望用户指定响应格式应该是 XML 还是 JSON?使用 HTTP 接受标头。
想要将客户端重定向到不同的 URL 以获取请求的结果?使用 HTTP 位置标头。
HTTP 的许多功能已经处理了您可能想做的许多事情。使用它们!
安全
性 这里有两个一般性问题需要解决:验证用户身份,以及确定给定用户可以执行的操作。
安全性:身份验证
用户需要在他们的请求中指定他们是谁。
想到的第一个解决方案是允许用户指定用户名和密码,可能与他们用于访问您的应用程序的用户名和密码相同。这表面上看起来是个好主意,但并不理想。
用户最终会将他们的用户名和密码烘焙到他们自己的应用程序中。不可避免地,一位用户会忘记他们的密码并更改密码,以便他们可以愉快地访问您的应用程序,并在此过程中破坏他们自己的应用程序。
更好的选择是让用户提供一个身份验证令牌,它本质上是一个对用户唯一的值,就像用户名和密码合二为一一样。
这允许您在逻辑上将用户名和密码与对 API 的访问分开。用户可以随时更改他们的应用程序的用户名和/或密码,而不会破坏他们对 API 的访问。
用户还可以拥有多个 API 令牌,每个令牌具有不同的访问级别,从而允许用户安全地将 API 令牌分发给第三方服务。
安全性:访问控制
就外界而言,您的 API 是一组 URL。根据定义,每个 URL 都是唯一的并执行唯一的任务。以这些概念为基础的访问控制机制是一个很好的起点。
我更愿意为每个令牌保留一个允许令牌访问的 URL 的列表。当使用给定的令牌访问 URL 时,很容易判断正在访问哪个 URL 以及它是否在令牌的允许 URL 列表中。
如果您明智地选择一组 URL,其中每个 URL 执行一个独特的操作,则此过程为您提供了您将获得的最佳访问控制级别。
为了提供更精细的控制,您可能还需要指定允许令牌访问的每个 URL,允许它们使用哪些查询参数。