寻找在Ruby on Rails中构建安全REST API的建议

时间:2008-10-29 14:54:53

标签: ruby-on-rails ruby security rest asp.net-web-api

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

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

与红宝石一样,我确信从那以后事情已经发生了变化。所以我的问题是,这仍然是在RoR中保护REST API的最佳方法吗?

如果不是您在“新项目”或“现有项目”情景中的建议?

4 个答案:

答案 0 :(得分: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请求都使用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更容易,而不是创建自己的密钥/签名系统。

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

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

答案 1 :(得分:7)

  

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

attr_accessibleattr_protected对于控制在ActiveRecord模型上执行批量分配的功能非常有用。你肯定想使用attr_protected来防止表单注入攻击;见Use attr_protected or we will hack you

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

请参阅Ruby on Rails Security Guide(Rails文档项目的一部分)获取更多有用信息。

答案 2 :(得分:3)

我现在面临着与你类似的问题,因为我也正在为rails应用程序构建一个REST api。

我建议确保只有可以由用户编辑的属性标记为attr_accessible。这将设置一个可以使用update_attributes分配的白色属性列表。

我做的是这样的:

   class Model < ActiveRecord::Base  
       attr_accessible nil  
   end

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

您知道有人可以不仅使用REST api而且还使用常规表单帖子来批量分配属性。

答案 3 :(得分:0)

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

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