12

我正在设计一个 JSON Web API,并希望通过唯一的 ID 来区分客户端,以监控使用情况并阻止恶意/行为不端的客户端。该 API 没有封装在 JavaScript 库中,也不是 Web 应用程序独有的,任何客户端类型都可以使用它(桌面、电话等)。

问题是,网络应用程序(官方网站)也是 API 本身的客户端,因此必须公开其 API 密钥。因此,某些用户可以直接从页面上的 JavaScript 中提取密钥并使用它,而不是生成自己的密钥。

是否有可能通过一些更好/更智能的设计选择以某种方式缓解这个问题,还是我必须接受这样一个事实,即任何恶意使用 API 的人都可以利用这一点?

我对前端应用程序 (EmberJS) 和后端服务器 (Go) 有 100% 的控制权,因此可以建议任何更改。

  • 我正在使用每个会话/IP 的速率限制来为这种情况添加额外的保护层
  • twitter.com 页面曾经也是它自己的 API 的客户端。他们是怎么解决的?

注意:问题不在于身份验证或安全性本身,而是如何要求第 3 方用户在身份验证之外(!)使用 API 密钥!

4

3 回答 3

6

您应该区分 Web 客户端和非 Web 客户端。Web 的访问密钥不能在非 Web 中使用,反之亦然。对于网络客户端,您可以进行引用检查等。您还可以为您的应用程序动态创建访问密钥并每天(或每个会话)自动更改它们。您还可以仅为您的应用添加一些特殊的验证,例如一些由混淆 JS 计算的附加密钥。

没有什么能阻止恶意用户模拟浏览器,执行 JS,操纵它,然后做坏事——但你可以让它变得足够烦人,以至于他们认为不值得他们努力。诸如权限等非常重要的事情显然需要在服务器端进行检查,因此滥用您的 API 应该不是什么大问题。您必须像处理常规 Web 应用程序滥用 - IP 块等一样,通过您网站的 API 密钥处理 API 滥用。

您仍然需要为非 Web 客户端的 API 密钥保密。这只能通过混淆来不可靠地完成,您可以将其交给客户端开发人员。如果他们的密钥被泄露和滥用,您将其撤销,他们将有动力修复它。

看看OAuth 2.0,它们包含许多可能对您有用的功能。即使你不想使用它,你也可以从中获得一些灵感。OpenStreetMap 使用 OAuth(不确定是 1 还是 2)作为基于 flash 的编辑器;只要登录用户从同一来源调用它,就会自动完成 OAuth 权限授予。对于第三方应用程序,用户需要手动完成。你可能想检查一下。

于 2013-01-28T13:35:44.890 回答
5

仅使用单个 API 密钥将无法使您的 API 安全。您所描述的 API 密钥基本上是一个公钥,您将需要某种类型的私钥来进行安全识别/身份验证以及一种传递它的机制。

你问 Twitter 是如何解决这个问题的。他们使用 Oath 1.0a。以下是Twitter 开发人员常见问题解答中关于它如何与 API 密钥绑定的简要说明。

大多数与 API 的集成都需要您通过 API 密钥向 Twitter 识别您的应用程序。在 Twitter 平台上,术语“API 密钥”通常指的是所谓的 OAuth 消费者密钥。此字符串在向 API 发出请求时标识您的应用程序。在 OAuth 1.0a 中,您的“API 密钥”可能是指此消费者密钥和“消费者秘密”的组合,该字符串用于安全地“签署”您对 Twitter 的请求。除了应用程序上下文之外,大多数对 Twitter 的请求都需要用户上下文。通过使用另一种称为“访问令牌”的令牌/密钥来呈现用户上下文。有关更多信息,请参阅获取访问令牌。

您可以在Apigee.com找到很多关于设计 API 的优秀资源。他们建议使用OAuth 2.0进行身份验证/授权。

这是关于如何使用HMAC 身份验证来保护 Web API的描述。

当我不得不使用仅使用 API 密钥的 API 时,我为我的 Web 应用程序使用了一种解决方法。我不直接从 Web 应用程序的客户端部分(即 Web 浏览器中的 JavaScript)访问 API。相反,我访问 API 服务器端并将 API 密钥加密存储在安全配置文件中。我为原始 API 提供了一个 Facade,并使用我自己的安全方法来保护依赖于应用程序类型的 Facade API。

于 2013-01-29T16:04:25.187 回答
-2

通用 API 工作流程:

  1. 客户端发送请求
  2. 请求经过身份验证和授权
  3. 数据被发回

网站 - 登录

  1. 用户登录提供用户名和密码
  2. 创建一个秘密并将其存储到一个 cookie 中

网站 - API 访问

  1. 客户端发送请求
  2. 根据 coockie 的秘密对请求进行身份验证和授权(cookie 随请求一起发送)
  3. 数据被发回

非 WEB 客户端 - 获取 API KEY(长随机字母数字字符串)

  1. 选项 1 - 用户在网站上注册客户端,获取 API KEY 并将其存储到客户端
  2. 选项 2 - 用户在客户端输入用户名和密码,客户端请求一个带有用户名和密码的 API KEY,密钥被返回并存储到客户端。用户名和密码不存储在客户端上。

非 WEB 客户端 - API 通信

  1. 客户端使用 API KEY 发送请求
  2. 请求基于 API-KEY 进行认证和授权
  3. 数据被发回

当使用选项 2 生成密钥时,您可以获得一些额外的数据,因为它来自客户端(操作系统、浏览器)。在这种情况下,当检查 API-KEY 时,如果用户更改了操作系统或浏览器,您可以强制用户生成一个新的

关键是您的 API 以两种方式对请求进行身份验证。使用 coockie 的秘密或 API KEY。因此无需在网站上公开 API-KEY。

请注意,对于使用 API-KEY 的客户端,不涉及会话。每个请求仅由 API-KEY 进行身份验证。所以那些客户端被认为是非 WEB 应用程序。

于 2013-01-29T11:44:07.060 回答