“私有”REST API 的安全性

Posted

技术标签:

【中文标题】“私有”REST API 的安全性【英文标题】:Security for "Private" REST API 【发布时间】:2012-03-06 00:29:40 【问题描述】:

我目前正在开发一个 Web 应用程序,该应用程序现在由一个前端组成,该前端使用我们编写的 REST API 显示数据并与之交互。唯一会使用该 API 的是我们的前端网站,以及在某个时候我们将开发的移动应用程序。

我已经阅读了大量关于 OAuth 如何成为保护 API 的理想机制的资料,现在我开始对它的工作原理有了很好的了解。

我的问题是——因为我从未将我的 API 访问权限授予第三方客户端,OAuth 真的有必要吗?有什么理由是有利的吗?此外,由于后端只是 API,因此没有可供用户进行身份验证的网关(例如,如果您正在使用 Twitter API 编写应用程序,当用户进行身份验证时,他们将被定向到 Twitter 页面以授予访问权限然后重定向回客户端)。

我不太确定该往哪个方向发展。似乎在 http 身份验证和 OAuth 之间必须有某种适合这种情况的方法,但我就是不明白。

【问题讨论】:

【参考方案1】:

在我看来,OAuth 优于其他选项的场景之一是与不受信任的客户端合作,无论这些客户端是由您还是第三方开发的。

什么是不受信任的客户端?从谁处理授予对 API 访问权限的凭据的角度来考虑。

例如,您的 Web 应用程序可以通过两种方式与您的 API 交互:
    您的 Web 应用服务器端与您的 API 对话。您的 Web 应用服务器是受信任的客户端,因为访问您的 API 的凭据只能由有权访问服务器的人访问……您和您的团队。您可以使用 client_id 和 client_secret 对 Web 应用服务器进行身份验证。 您可能希望从使用 javascript 在最终用户浏览器上运行的 Web 应用程序客户端直接调用 API。最终用户的浏览器是不受信任的客户端。如果您要将 API 的凭据传递到浏览器,任何人都可以检查 JavaScript 代码并窃取您的凭据。

第三方原生应用也不可信。使用您的 API 的恶意开发人员可能会保存您平台的凭据和最终用户。

您的 Native App 是受信任的客户端,可以使用简单的用户名、密码和标识您的 App 的客户端 ID 来管理身份验证。

OAuth 如何提供帮助? OAuth Authorization code 和 Implicit 授权可以帮助您解决这个问题。这些流程仅适用于支持重定向的客户端,例如浏览器。并让您针对您的授权服务器对不受信任的客户端和用户进行身份验证,以访问您的资源服务器、您的 API,而不会暴露凭据。看看RFC 看看它是如何完成的。

OAuth 的好处在于它不仅支持这些基于重定向的身份验证流程,而且还支持客户端凭据授予和用户凭据授予。因此,OAuth 授权服务器将涵盖所有情况。

【讨论】:

【参考方案2】:

OAuth 2.0 最初看起来像是一个 PITA,如果您考虑必须自己构建很多 OAuth 2.0,但大多数语言都有一些非常可靠的 OAuth 2.0 设置,您可以通过不同数量的摆弄来固定它们。如果您使用的是 Laravel 或 RoR 之类的框架,那么它几乎没有任何工作。

php:http://oauth2.thephpleague.com/ 红宝石(导轨或葡萄):https://github.com/doorkeeper-gem/doorkeeper

如果您不想按照帖子中的建议重定向用户,请忽略其他有关两条腿流的 cmets 和答案。您可以使用 client_credentials 授权类型让应用只提供其客户端 ID 和机密以换取访问令牌,这既方便又简单。

我会问我们谈话的私密性如何,因为如果唯一与它交谈的系统在后端并且与外界没有交互,那么你可能会让它完全开放,只依靠网络来保证它的安全( ***/防火墙)。

但如果它在“我们的 iPhone 应用程序使用它”的意义上是私有的,那么您肯定希望使用 OAuth 2.0 或类似的东西。

【讨论】:

【参考方案3】:

2 腿 OAuth 可能是您想要使用的。它基本上是对共享密钥进行哈希处理,但您的优势是不必自己编写代码。

这是一个相关的问题:Two-legged OAuth - looking for information

【讨论】:

使用 OAuth 有什么好处? 您不必自己编写身份验证代码 :) 并且它经过了良好的测试和信任。使用 2 腿 OAuth,您只需要在服务器和 api 调用者之间共享一个私钥,任何窥探者都无法弄清楚该密钥是什么(尽管您可能希望通过 SSL 运行连接) . 好的。所以这个想法是使用用户名和密码以及使用私钥的签名处理通过 API 的登录,授予令牌,然后为将来的调用使用令牌和签名用于会话的剩余部分? 在您的情况下,私钥可能只是用户密码。在code.google.com/p/oauth-php/wiki/ConsumerHowTo#Two-legged_OAuth 的示例中,$key 是用户名,$secret 是密码。 但这意味着我必须将所有用户名和密码以纯文本形式存储在客户端服务器上以用于签名【参考方案4】:

您应该将 Oauth 用于移动设备与 API 层的通信。

但是,Oauth 在这个 Web UI 层对中间层访问(机器对机器)没有任何好处。

另一方面也有一些潜在的问题

    管理访问令牌过期变得很痛苦。考虑到您的 UI 必须跨集群中的多个节点缓存访问令牌。过期时刷新它,UI层正在与后端协商安全性这一事实偶尔会花费额外的时间。

    在两条腿的 Oauth(OAuth 客户端凭据,如 v2.0)中不支持任何加密。因此,您仍然需要将密钥和秘密都发送到服务器以获取访问令牌。

    后端必须实现发布访问令牌、刷新令牌、验证访问令牌等,没有任何显着的好处

【讨论】:

以上是关于“私有”REST API 的安全性的主要内容,如果未能解决你的问题,请参考以下文章

ReST API 安全性

Jersey REST API 安全性

REST 控制器的 Spring 安全性

java rest api接口 怎么保证安全性

Flutter REST API 安全性

笔记:Jersey REST API 设计