66

我开始为我正在从事的项目构建 REST API,这让我对使用 RoR 构建 API 的最佳方式进行了一些研究。我很快发现,默认情况下,模型是向世界开放的,并且可以通过 URL 调用,只需在 URL 末尾添加一个“.xml”并传递适当的参数即可。

那么接下来的问题来了。如何保护我的应用程序以防止未经授权的更改?在做一些研究时,我发现了几篇关于它们attr_accessible以及attr_protected如何使用它们的文章。我发现谈论这些的特定 URL 是在 07 年 5 月发布的(这里)。

与所有的红宝石一样,我相信从那时起事情已经发展了。所以我的问题是,这仍然是在 RoR 中保护 REST API 的最佳方式吗?

如果不是,您在“新项目”或“现有项目”场景中有何建议?

4

4 回答 4

102

有几种认证 API 请求的方案,它们不同于由 restful_authentication 或acts_as_authenticated 等插件提供的普通认证。最重要的是,客户端不会维护会话,因此没有登录的概念。

HTTP 身份验证

您可以使用基本 HTTP 身份验证。为此,API 客户端将使用常规用户名和密码,并将其放入 URL 中,如下所示:

http://myusername:mypass@www.someapp.com/

我相信 restful_authentication 开箱即用地支持这一点,因此您可以忽略是否有人通过 API 或浏览器使用您的应用程序。

这里的一个缺点是您要求用户在每个请求中都清楚地输入他们的用户名和密码。通过 SSL 执行此操作,您可以确保此操作安全。

不过,我认为我实际上从未见过使用此 API 的 API。对我来说,这似乎是一个不错的主意,特别是因为当前的身份验证方案开箱即用地支持它,所以我不知道问题出在哪里。

API 密钥

启用 API 身份验证的另一种简单方法是使用 API 密钥。它本质上是远程服务的用户名。当有人注册使用你的 API 时,你给他们一个 API 密钥。这需要与每个请求一起传递。

这里的一个缺点是,如果有人获得了其他人的 API 密钥,他们可以以该用户的身份发出请求。我认为通过让所有 API 请求都使用 HTTPS (SSL),可以在一定程度上抵消这种风险。

另一个缺点是用户在任何地方都使用相同的身份验证凭据(API 密钥)。如果他们想撤销对 API 客户端的访问,他们唯一的选择是更改他们的 API 密钥,这也会禁用所有其他客户端。这可以通过允许用户生成多个 API 密钥来缓解。

API Key + Secret Key 签名

已弃用(某种程度) - 请参阅下面的 OAuth

使用密钥签署请求要复杂得多。这就是 Amazon Web Services(S3、EC2 等)所做的。本质上,您给用户 2 个密钥:他们的 API 密钥(即用户名)和他们的密钥(即密码)。API 密钥与每个请求一起传输,但密钥不是。相反,它用于对每个请求进行签名,通常是通过添加另一个参数。

IIRC,亚马逊通过将所有参数带到请求中并按参数名称对它们进行排序来实现这一点。然后,使用用户的密钥作为散列密钥对该字符串进行散列。这个新值在发送之前作为新参数附加到请求中。在亚马逊方面,他们做同样的事情。它们获取所有参数(签名除外),对它们进行排序,并使用密钥进行散列。如果这与签名匹配,他们就知道该请求是合法的。

这里的缺点是复杂性。让这个方案正常工作对于 API 开发人员和客户来说都是一件痛苦的事情。期待大量来自无法让事情正常工作的客户开发人员的支持电话和愤怒的电子邮件。

身份验证

为了解决密钥 + 秘密签名的一些复杂性问题,出现了一个名为OAuth的标准。OAuth 的核心是一种密钥 + 秘密签名,但其中大部分是标准化的,并已包含在许多语言的库中

一般来说,API 生产者和消费者都更容易使用 OAuth,而不是创建自己的密钥/签名系统。

OAuth 还固有地对访问进行细分,为每个 API 使用者提供不同的访问凭证。这允许用户有选择地撤销访问而不影响他们的其他消费应用程序。

特别是对于 Ruby,有一个OAuth gem可以为 OAuth 的生产者和消费者提供开箱即用的支持。我已经使用这个 gem 来构建 API 并使用 OAuth API,印象非常深刻。如果您认为您的应用程序需要 OAuth(而不是更简单的 API 密钥方案),那么我可以轻松推荐使用 OAuth gem。

于 2008-10-30T14:16:41.060 回答
7

如何保护我的应用程序以防止未经授权的更改?

attr_accessible并且attr_protected对于控制在 ActiveRecord 模型上执行批量分配的能力都很有用。您肯定想使用 attr_protected 来防止表单注入攻击;请参阅使用 attr_protected 否则我们将破解您

此外,为了防止任何人能够访问您的 Rails 应用程序中的控制器,您几乎可以肯定需要某种用户身份验证系统并before_filter在您的控制器中放置一个以确保您有一个授权用户发出请求在您允许执行请求的控制器操作之前。

有关更多有用信息,请参阅Ruby on Rails 安全指南(Rails 文档项目的一部分)。

于 2008-10-29T19:28:48.920 回答
3

我目前面临与您类似的问题,因为我还在为 Rails 应用程序构建 REST api。

我建议确保只有可以用户编辑的属性才用 attr_accessible 标记。这将设置可以使用 update_attributes 分配的属性白名单。

我所做的是这样的:

   class Model < ActiveRecord::Base  
       attr_accessible nil  
   end

我所有的模型都继承自它,因此他们被迫为他们想要批量分配的任何字段定义 attr_accessible。就个人而言,我希望有一种方法可以默认启用此行为(可能有,但我不知道)。

只是为了让您知道有人不仅可以使用 REST api 还可以使用常规表单发布来批量分配属性。

于 2008-10-29T15:06:42.117 回答
0

另一种节省自己构建大量东西的方法是使用http://www.3scale.net/之类的东西,它为个人开发人员处理密钥、令牌、配额等。它还进行分析并创建开发人员门户。

有一个 ruby​​/rails 插件ruby​​ API 插件,它将在流量到达时应用于流量策略 - 您可以将它与oAuth gem结合使用。您也可以通过在应用程序前面放置 varnish 并使用 varnish lib mod: Varnish API Module来使用它。

于 2012-06-03T12:55:04.320 回答