宁静的Web服务身份验证

时间:2010-08-28 20:29:01

标签: web-services authentication restful-authentication rest

我有一个Restful Web服务API,正由不同的第三方使用。该API的一部分受到限制(您需要用户名/密码才能访问它)。我想知道实现身份验证的最佳方式是什么?

我正在使用https,因此通信已加密。我有两个想法:

  • 在用户开始使用(受限制)服务之前,它会使用POST发送用户名/密码(因为正在使用https,因此凭据已加密)。登录成功后,服务器会发回与此用户名匹配的随机一次性使用值(nonce)。当发出下一个请求时,除了用户名,客户端发送先前返回的现时。服务器匹配username和nonce,并沿着请求的数据返回新的nonce。每个新请求都使用新的nonce。基本上,这是Digest访问身份验证的轻量级版本。
  • 由于此API是从第三方使用的,因此用户名/密码可用于每个(受限制的)请求。由于正在使用https,因此它们将被加密。这种方法的缺点是这不符合Restful(POST将始终使用)。

我更接近选择第一种方法(它是Restful兼容,相对容易实现,XML,json或html可以在不改变的情况下使用),但我想看看你的意见是什么?你推荐什么:第一种,第二种或第三种方法?

不过,我在服务器端使用Python。

4 个答案:

答案 0 :(得分:23)

我在API中看到这种方式(以及目前正在实施的方式)的一种方法是创建一个名为 Session 的RESTful资源,该资源通过 POST 创建它提供用户名和密码。

基本上我是如何实现的:

POST /sessions { Username: "User", Password: "Password" }

创建时间限制会话并返回包含会话密钥值和到期的会话资源。您可能还希望将此值作为cookie值返回,以便于实现API客户端。

DELETE /session/{id}

立即使会话过期,因此无法再使用它。这用于显式注销。

然后我让用户通过查询参数附加会话密钥,虽然您也可以允许它通过cookie值提交,我建议同时允许它们。

我更喜欢这个是非常简单。

显然,您的方案将在某种程度上决定您的会话应该如何管理,也许它们不受时间限制并且无限期地持续,并且可能为了增加安全性而对它们进行散列或加密。

如果你到处使用HTTPS,你可能不需要太担心。但是,如果要使用HTTP,则需要使用哈希和密钥之类的东西,并说出时间戳以按请求生成安全密钥。这样,您可以通过HTTPS共享密钥,然后切换到HTTP以进一步调用。即使有人设法从请求中嗅出密钥,它几乎可以立即过期并且无用。

免责声明:我不是安全专家; - )。

答案 1 :(得分:8)

没有理由不在此处使用HTTP身份验证。

也就是说,POST获取时间块nonce的概念可以很好地工作。但这就是为什么你需要首先跳过这个额外的箍的动机。

当使用bcrypt哈希作为原始密码时考虑了这种技术,因为验证用户的实际费用(如果你不知道,可以调整bcrypt以便花费大量实时来执行哈希函数)。选择是使用密码通过bcrypt通过昂贵的验证过程提供服务“登录”的选项,然后获得时间阻止令牌以换取将绕过bcrypt进程的未来请求

对于bcrypt进程,使用HTTP身份验证,该服务既可以使用普通密码,也可以使用令牌。这样,用户可以随时使用密码进行服务,但这只会变得昂贵。所以他们可以做到这一点,他们只是不应该这样做。该服务不关心客户端使用哪种身份验证技术。

nonce服务是为了提高吞吐量而提供的。

除此之外,它是标准的HTTP身份验证,但采用了新方案。

答案 2 :(得分:6)

亚马逊网络服务做得很好,查看一些想法的方法。基本上,他们让客户端使用他们的密码加密特殊的http头。

这是链接:

http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html

答案 3 :(得分:4)

假设服务从未在浏览器中使用,并且通信仍然是加密的,我认为第二种方法的变体没有坏处:添加X-Headers以发送每个请求的用户名/密码,例如:

GET /foo HTTP/1.1
Host: www.bar.com
X-MyUsername: foo
X-MyPassword: bar

另一个想法是使用HTTP Basic Auth并发送Authorization: Basic base64(user:password) - 标题。也就是说,如果连接始终是加密的。