2008-10-29 69 views
65

我正在开始为我正在开发的项目构建REST API,并且这让我做了一点研究,以了解最佳方式使用RoR构建API。我很快发现,默认情况下,模型向全世界开放,只需在URL末尾添加一个“.xml”并传递适当的参数即可通过URL调用。寻找在Ruby on Rails中构建安全REST API的建议

那么下一个问题就来了。如何保护我的应用程序以防止未经授权的更改?在做一些研究时,我发现一些文章谈论了attr_accessibleattr_protected以及它们如何使用。我在07年5月发现了关于这些网站的特定网址(here)。

就像所有的事情一样,我相信事情自那时起就有了进步。所以我的问题是,这仍然是在RoR中保护REST API的最佳方式吗?

如果不是您在“新项目”或“现有项目”方案中提出的建议如何?

+0

如果客户端知道如何操作您的URI(通过附加.xml或其他方式),那么您的API不是REST。 – aehlke 2009-08-18 14:59:32

+0

这是一个很好的Oauth 2.0服务器库ruby https://github.com/Lelylan/rest-oauth2-server – sparkle 2012-04-05 20:36:16

回答

100

有几种验证API请求的方案,它们与插件(如restful_authentication或acts_as_authenticated)提供的常规验证不同。最重要的是,客户不会维护会话,所以没有登录的概念。

HTTP认证

您可以使用基本的HTTP认证。对于这一点,API客户端将使用常规的用户名和密码,只要把它的URL像这样:

http://myusername:[email protected]/ 

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

这里的一个缺点是您要求用户在每个请求中都明确地输入用户名和密码。通过SSL实现,可以使其安全。

虽然我不认为我真的看到过使用此API的API。对我来说,这似乎是个不错的主意,尤其是因为它是由当前的认证方案开箱即用的,所以我不知道问题出在哪里。

API密钥

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

这里的一个缺点是,如果任何人获取他人的API密钥,他们可以以该用户的身份发出请求。我认为,通过使所有的API请求都使用HTTPS(SSL),您可以稍微抵消一些风险。

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

API密钥+秘密密钥签名

已过时(在某种程度上) - 见下文

复杂得多OAuth是签署同一个密钥请求。这就是亚马逊网络服务(S3,EC2等)的功能。基本上,你给用户2个密钥:他们的API密钥(即用户名)和他们的密钥(即密码)。 API密钥随每个请求一起传输,但密钥不是。相反,它通常通过添加另一个参数来用于签署每个请求。

IIRC亚马逊通过将所有参数提交给请求并通过参数名称对其进行排序来完成此操作。然后,使用用户的密钥作为散列键,散列该字符串。这个新值在被发送之前作为新的参数附加到请求中。在亚马逊方面,他们也做同样的事情。他们采取所有参数(签名除外),排序他们,并使用密钥散列。如果这符合签名,他们知道该请求是合法的。

这里的缺点是复杂性。让这个方案正确工作对于API开发人员和客户来说都是一种痛苦。预计会有很多来自客户开发人员的支持电话和愤怒的电子邮件,他们无法启动工作。

的OAuth

为了解决一些与键+秘密签署的复杂性问题,标准已经出现所谓的OAuth。在核心OAuth是一个密钥+秘密签名的味道,但其中大部分是标准化的,已被纳入libraries for many languages

一般来说,API生产者和消费者使用OAuth比创建自己的密钥/签名系统要容易得多。

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

专门针对Ruby,有一个OAuth gem,为OAuth的生产者和消费者提供开箱即用的支持。我已经使用这个gem来构建一个API并且使用OAuth API,并且给我留下了深刻的印象。如果您认为您的应用程序需要OAuth(与简单的API密钥方案相反),那么我可以轻松推荐使用OAuth gem。

3

我现在正面临着类似的问题,因为我还为Rails应用程序构建了一个REST API。

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

我做的是这样的:

class Model < ActiveRecord::Base 
     attr_accessible nil 
    end 

我所有的车型从继承,使他们被迫定义为attr_accessible他们希望制造大规模分配的任何领域。就我个人而言,我希望有一种方法可以默认启用此行为(可能有,我不知道)。

只要你知道有人可以批量分配一个属性不仅使用REST API,但也使用常规的形式发布。

7

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

attr_accessibleattr_protected是用于控制对一个ActiveRecord模型上执行质量分配的能力都非常有用。你一定要使用attr_protected来防止表单注入攻击;请参阅Use attr_protected or we will hack you

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

请参阅Ruby on Rails Security Guide(Rails文档项目的一部分)了解更多帮助信息。

0

另一种节省构建大量资料的方法是使用类似http://www.3scale.net/的方法,它可以为个别开发人员处理密钥,令牌,配额等。它也进行分析并创建开发者门户。

有一个ruby/rails插件ruby API plugin它将适用于流量到达时的策略 - 您可以将它与oAuth gem一起使用。您也可以通过在应用程序前面清除清漆并使用清漆lib mod:Varnish API Module来使用它。