REST API 授权和身份验证(网络 + 移动)

Posted

技术标签:

【中文标题】REST API 授权和身份验证(网络 + 移动)【英文标题】:REST API Authorization & Authentication (web + mobile) 【发布时间】:2012-03-12 07:35:51 【问题描述】:

我已经阅读过 oAuth、Amazon REST API、HTTP Basic/Digest 等内容,但无法将其全部归为“单件”。这可能是最接近的情况 - Creating an API for mobile applications - Authentication and Authorization

我想建立以 API 为中心的网站 - 服务。所以(一开始)我会在中心有一个 API,websitephp + mysql)将通过 cURLAndroid 连接>iPhone 通过他们的网络接口。所以 3 个主要客户端 - 3 个 API 密钥。任何其他开发人员也可以通过 API 接口进行开发,他们将获得自己的 API 密钥。 API 操作将根据 userLevel 状态被接受/拒绝,如果我是管理员,我可以删除任何内容等,所有其他人只能操纵他们的本地(帐户)数据。

首先,授权 - 我应该使用 oAuth + xAuth 还是我自己的某种实现(参见 http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/RESTAuthentication.html?r=9197)?据我了解,在 Amazon 服务用户是 == API 用户(具有 API 密钥)。在我的服务中,我需要将标准用户/帐户(在网站上注册的那个)和开发者帐户(应该有他们的 API 密钥)分开。

所以我首先需要授权 API 密钥,然后验证用户本身。如果我使用 Amazon 的方案来检查开发人员的 API 密钥(授权他们的应用程序),我应该使用哪个 sheme 进行用户身份验证?

在(通过HTTPS,HTTP Basic)发布我的用户名和密码之后,我读到了有关通过api.example.org/auth 获取令牌的信息,然后在每个后续请求中转发它。如果我同时登录 Android网站,如何管理令牌?如果我只在第一次请求时使用 SSL(当传输用户名和密码时)而在其他所有请求中只使用 HTTP,那么中间人攻击呢?在这个例子中这不是问题吗Password protecting a REST service?

【问题讨论】:

【参考方案1】:

与往常一样,保护密钥的最佳方法是不传输它。

也就是说,我们通常使用一种方案,其中每个“API 密钥”都包含两部分:一个非秘密 ID(例如 1234)和一个秘密密钥(例如 byte[64])。

如果您提供 API 密钥,请将其存储(加盐和散列)在您的 服务的数据库。 如果您提供用户帐户(受密码保护),请将 服务数据库中的密码(加盐和散列)

现在,当消费者首先访问您的 API,进行连接时,让他

发送“用户名”参数(“john.doe”不是机密) 发送“APIkeyID”参数(“1234”,非机密)

把他还给他

数据库中的盐(如果参数之一错误, 只是回馈一些可重复的盐-例如。 sha1(用户名+"notverysecret")。 服务器的时间戳

消费者应该在会话期间存储盐以保持快速和顺利,他应该计算并保持客户端和服务器之间的时间偏移。

消费者现在应该计算 API 密钥和密码的加盐哈希值。这样,消费者就拥有与存储在数据库中的完全相同的密码和 API 密钥哈希值,但不会有任何秘密通过网络传输。

现在,当消费者随后访问您的 API 以进行实际工作时,让他

发送“用户名”参数(“john.doe”不是机密) 发送“APIkeyID”参数(“1234”,非机密) 发送“RequestSalt”参数(字节[64],随机,非机密) 发送“RequestTimestamp”参数(根据客户端时间和已知偏移量计算) 发送“RequestToken”参数(hash(passwordhash+request_salt+request_timestamp+apikeyhash))

服务器不应该接受超过 2 秒的时间戳,以防止重放攻击。

服务器现在可以计算与客户端相同的哈希值(passwordhash+request_salt+request_timestamp+apikeyhash),并且可以确定

客户端知道 API 密钥, 客户端知道正确的密码

【讨论】:

很好的答案,谢谢。但是我可以通过在 UTC 时间设置客户端和服务器来逃避“时间偏移”吗?或者作为亚马逊提供 /date GET 请求来计算偏移量? 当然可以。时间戳对于重播安全性很重要,所以任何适合你的都可以。如果两端都有NTP,可以省略offset计算步骤。 您使用哪种散列方法或只是为了确保盐足够长?有人说尽可能安全 - SHA256/512,甚至使用 HMAC? 我们使用 sha256 和 ca。 100 字节盐。这应该需要天文资源才能恢复。 TLS/SSL 有很多话要说 - 一个重要的部分是,它提供了完整对话的机密性。反对 SSL 也有很多话要说:安装程序可以是一个 PITA,尤其是对于外来设备/操作系统。如果您确实不需要需要保密,但需要身份验证,那么上述解决方案就可以了。

以上是关于REST API 授权和身份验证(网络 + 移动)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Laravel 中为 REST API 创建身份验证

Django REST Framework - API 身份验证 - 授权应用程序而不是用户

401- 使用 REST API Dynamics CRM 和 Azure AD 进行未经授权的身份验证

REST API 和移动应用的身份验证策略

Web 应用程序和移动应用程序的 REST API 身份验证

如何管理从本地移动应用程序调用 Play2!-Scala REST 服务发送的用户请求的身份验证/授权