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

于是下一个问题来了.如何保护我的应用程序以防止未经授权的更改?在做一些研究时,我发现了几篇关于attr_accessibleattr_protected以及如何使用它们的文章.我在2007年5月(here)发布了一个关于这些内容的特定URL.

和所有ruby的东西一样,我相信从那时起事情就发生了变化.所以我的问题是,这仍然是在RoR中保护REST API的最佳方法吗?

如果不是,在"新项目"或"现有项目"场景中,你有什么建议?

推荐答案

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

HTTP Authentication

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

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

我相信restful_认证支持这种开箱即用的方式,所以你可以忽略是否有人通过API或浏览器使用你的apply.

这里的一个缺点是,你要求用户在每个请求中都将用户名和密码放在明文中.通过SSL,您可以确保安全.

不过,我觉得我从来没有见过真正使用这个的API.对我来说,这似乎是一个不错的主意,尤其是因为当前的身份验证方案对它提供了开箱即用的支持,所以我不知道问题出在哪里.

API Key

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

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

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

API Key + Secret Key signing

Deprecated(sort of) - see OAuth below

更复杂的是使用密钥对请求进行签名.这就是Amazon Web服务(S3、EC2等)所做的.基本上,你给用户两个密钥:他们的API密钥(即用户名)和他们的密钥(即密码).每个请求都会传输API密钥,但不会传输密钥.相反,它通常通过添加另一个参数来对每个请求进行签名.

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

缺点是复杂性.对于API开发人员和客户来说,让这个方案正常工作都是一件痛苦的事情.客户开发人员可能会打很多支持电话,发很多愤怒的邮箱,但他们无法让事情顺利进行.

OAuth

为了解决密钥+秘密签名的一些复杂问题,出现了一个名为OAuth的标准.OAuth的核心是密钥+秘密签名,但其中大部分是标准化的,已被纳入libraries for many languages.

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

OAuth还固有地对访问进行分段, for each API使用者提供不同的访问凭证.这允许用户有 Select 地撤销访问,而不会影响其他消费应用程序.

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

Ruby-on-rails相关问答推荐

使用超级用户角色和未知密码创建与POSTRES用户的连接

Grape api (rails) - 未初始化常量 Endpoints::TodoAPI (NameError)

使用拆分成多个部分的种子文件进行Rails数据种植

创建大哈希的 Ruby 方法

Ruby on rails 查询不知道怎么写

无效的单表继承类型:Rails

2个空格或1个制表符,Rails社区的缩进标准是什么?

Rails:如何小写非英文字符串?

如何添加到序列化数组

在 Windows 上使用 Ruby 进行开发

Ruby on Rails 的 varchar 迁移问题

我如何存根 find_each 以在 rails 3 中进行 rspec 测试

可能在rails中有多态has_one关系?

在 where 查询中查找 nil has_one 关联

关闭 Firefox 中文本字段的自动完成功能

如何在 VS Code 中自动格式化 Ruby 或 .erb 文件?

Rails Associations - has_many => :through - 但相同的模型

从任何编码强制字符串为 UTF-8

如何检测rails是否在根url?

Rails:如何在rails中使用dependent::destroy?