API 身份验证方法 - 我做得对吗?

API Authentication Method - am I doing it correctly?

我对构建 API 身份验证非常陌生 - 所以想确保我以正确的方式进行此操作,因为可能存在我不知道的重大安全漏洞。

它基于 secret/private 密钥对,其中客户端和服务器都知道密钥,但显然从未通过网络传递。

对于此方法的任何反馈、见解或漏洞,我们将不胜感激。


第 1 步:


客户端想要向 API 发出请求,因此向服务器请求随机数 - 传递他们的 public 密钥。



第 2 步:


服务器查找用户私钥(使用提供的 public 密钥)并使用随机的 32 个字符串(随机数)对其进行哈希处理 (sha256)。

散列的随机数和 public 密钥然后存储到本地数组。

然后服务器用随机数的未散列版本响应客户端。



第 3 步:


客户端从响应中获取随机数,并使用它的私钥(客户端在本地拥有)对其进行哈希处理。

然后它向服务器发出请求(连同它要执行的 API 任务)并发送它的散列随机数版本和 public 密钥。



第 4 步:


服务器获取客户端 public 密钥和散列随机数,然后检查本地数组以查看 public key/nonce 对是否存在。

如果该对存在;身份验证通过,请求被允许,public key/nonce 对从本地数组中删除。

首先让我说我在安全领域没有任何资历。请对我所说的一切持保留态度。

几个一般的想法

您似乎想推出自己的产品,这在任何与安全相关的领域都是一个坏主意。当有几种经过实战检验的替代方案时更是如此。

我想不出三种广泛使用的 API 身份验证方法:

  1. 基本身份验证。 Github 将此作为 fall-back 提供:“旨在用于脚本或测试(即,完全 OAuth 会过大的情况)。”

  2. OAuth. Github, Twitter, Facebook, LinkedIn, Google 都用这个。这个协议是明确指定的,但对于较小的项目来说可能有点矫枉过正。由于广泛的客户端库,它很容易实现。

  3. 基于哈希的消息身份验证代码 (HMAC)。 所有 Amazon Web 服务都使用它。这可能是最不受重视的解决方案,因为它在概念上比 OAuth 更容易:客户端使用其私钥签署请求并在请求中发送签名 + public 密钥。服务器使用客户端发送的 public 密钥查找私钥,然后创建请求的签名。如果签名匹配,则请求有效。 Public 和私钥必须事先交换(AWS 让你下载一次私钥)。

根据您的描述,HMAC 是最接近您想要的候选者。

针对您的建议的一些具体想法

  1. 您的算法要求您在服务器上保持状态(提示“本地数组”)。这对于单个服务器来说很好,但是当你扩展时你会做什么?当第 2 步命中一个服务器而第 3 步命中另一个服务器时,必须共享状态。您当然可以使用共享数据库(或缓存)或其他任何东西,但您必须考虑这一点。

  2. 往返次数。 需要像您建议的那样进行两步身份验证,每个客户端都必须为每个( payload) 请求或者你已经考虑过什么时候在服务器上使你的对无效。 HMAC 在没有请求开销的情况下基本上做同样的事情。

  3. 可能的攻击: 我可以用客户端请求随机数来淹没你的服务器。根据您的 public 密钥长度,我可能会想出有效的 public 密钥,并且我可以绑定从未用于第二个请求的资源。根据您的处理方式(另见第 1 点),我可能会关闭您的服务器。