基于令牌的REST API认证 [英] REST API Token-based Authentication

查看:303
本文介绍了基于令牌的REST API认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个REST API要求身份验证。因为认证通过自身通过HTTP web服务的外部时,我的理由是,我们将免除标记,以避免重复调用验证服务。这让我想起整齐我的第一个问题:

I'm developing a REST API that requires authentication. Because the authentication itself occurs via an external webservice over HTTP, I reasoned that we would dispense tokens to avoid repeatedly calling the authentication service. Which brings me neatly to my first question:

这是真的没有更好的不仅仅是要求客户端使用HTTP基本认证对每个请求和缓存调用验证服务服务器端?

基本验证解决方案具有无需对内容就可以开始请求之前一个完整的往返到服务器的优势。令牌有可能成为更灵活的范围(即仅授予权限对特定资源或动作),但似乎更适合比我更简单的用例OAuth的背景。

The Basic Auth solution has the advantage of not requiring a full round-trip to the server before requests for content can begin. Tokens can potentially be more flexible in scope (i.e. only grant rights to particular resources or actions), but that seems more appropriate to the OAuth context than my simpler use case.

目前令牌获得这样的:

curl -X POST localhost/token --data "api_key=81169d80...
                                     &verifier=2f5ae51a...
                                     &timestamp=1234567
                                     &user=foo
                                     &pass=bar"

API_KEY 时间戳验证是必需的所有请求。 校验是由返回:

The api_key, timestamp and verifier are required by all requests. The "verifier" is returned by:

sha1(timestamp + api_key + shared_secret)

我的本意是只允许从已知的各方,并prevent被逐字重复呼叫。

My intention is to only allow calls from known parties, and to prevent calls from being reused verbatim.

这是不够好? Underkill?矫枉过正?

在手令牌,客户可以获取资源:

With a token in hand, clients can acquire resources:

curl localhost/posts?api_key=81169d80...
                    &verifier=81169d80...
                    &token=9fUyas64...
                    &timestamp=1234567

有关可能的最简单的通话,这似乎是一种可怕的冗长。考虑到 shared_secret 将结束被嵌入在(至少)iOS应用程序,从中我会假设它可以提取,超出的错觉这甚至提供什么安全?

For the simplest call possible, this seems kind of horribly verbose. Considering the shared_secret will wind up being embedded in (at minimum) an iOS application, from which I would assume it can be extracted, is this even offering anything beyond a false sense of security?

推荐答案

让我单独的一切,解决方法每个问题隔离:

Let me seperate up everything and solve approach each problem in isolation:

验证

有关的认证,baseauth具有的优点是它是在协议级成熟溶液。这意味着很多的以后可能会突然出现的问题都已经解决了你。例如,BaseAuth,用户代理知道密码是一个密码,这样他们就不会进行缓存。

For authentication, baseauth has the advantage that it is a mature solution on the protocol level. This means a lot of "might crop up later" problems are already solved for you. For example, with BaseAuth, user agents know the password is a password so they don't cache it.

验证服务器负载

如果您分配令牌给用户,而不是你的服务器缓存的认证,你还在做同样的事情:缓存认证信息。唯一的区别是,你正在转向的缓存对用户的责任。这似乎是对没有收益的用户不必要的劳动,所以我建议透明地处理这个服务器上如你所说。

If you dispense a token to the user instead of caching the authentication on your server, you are still doing the same thing: Caching authentication information. The only difference is that you are turning the responsibility for the caching to the user. This seems like unnecessary labor for the user with no gains, so I recommend to handle this transparently on your server as you suggested.

传输安全

如果可以使用SSL连接,这一切就是这么简单,连接可靠*。以prevent偶然的多个执行,可以过滤多个网址,或要求用户在URL中包括随机成分(现时)。

If can use an SSL connection, that's all there is to it, the connection is secure*. To prevent accidental multiple execution, you can filter multiple urls or ask users to include a random component ("nonce") in the URL.

url = username:key@myhost.com/api/call/nonce

如果这是不可能的,而且传输的信息不是秘密,我建议使用安全哈希的请求,因为你在令牌的方法建议。由于散列提供了安全性,您可以指示用户提供的哈希作为baseauth密码。为了提高稳健性,我建议使用一个随机字符串代替时间戳作为现时,以prevent重放攻击(二合法的请求可能在同一秒进行)。相反,单独提供共享的秘密和API密钥的字段,你可以简单地使用API​​密钥共享密钥,然后使用不更改为prevent彩虹表攻击的盐。用户名字段似乎是一个好地方放现时也一样,因为它是身份验证的一部分。所以,现在你有一个干净的调用是这样的:

If that is not possible, and the transmitted information is not secret, I recommend securing the request with a hash, as you suggested in the token approach. Since the hash provides the security, you could instruct your users to provide the hash as the baseauth password. For improved robustness, I recommend using a random string instead of the timestamp as a "nonce" to prevent replay attacks (two legit requests could be made during the same second). Instead of providing seperate "shared secret" and "api key" fields, you can simply use the api key as shared secret, and then use a salt that doesn't change to prevent rainbow table attacks. The username field seems like a good place to put the nonce too, since it is part of the auth. So now you have a clean call like this:

nonce = generate_secure_password(length: 16);
one_time_key = nonce + '-' + sha1(nonce+salt+shared_key);
url = username:one_time_key@myhost.com/api/call

这是事实,这是一个有点费力。这是因为你不使用的协议级的解决方案(如SSL)。所以它可能是一个好主意,提供一些SDK给用户这样至少他们没有通过它自己去。如果你需要做这种方式,我觉得安全级别合适的(刚刚右杀)。

It is true that this is a bit laborious. This is because you aren't using a protocol level solution (like SSL). So it might be a good idea to provide some kind of SDK to users so at least they don't have to go through it themselves. If you need to do it this way, I find the security level appropriate (just-right-kill).

安全保密存储

这取决于你是谁试图阻挠。如果你是preventing访问到用户的手机的人从用户的姓名使用REST服务,那么这将是一个好主意,找到目标OS上的某种钥匙圈的API并具有SDK(或实施者)存储密钥那里。如果这是不可能的,你至少可以使它有点难以通过加密和存储加密数据,并在单独的地方加密密钥获得的秘密。

It depends who you are trying to thwart. If you are preventing people with access to the user's phone from using your REST service in the user's name, then it would be a good idea to find some kind of keyring API on the target OS and have the SDK (or the implementor) store the key there. If that's not possible, you can at least make it a bit harder to get the secret by encrypting it, and storing the encrypted data and the encryption key in seperate places.

如果你想保持其他软件供应商让你的API密钥,以prevent备用客户端的发展,只有加密和商店,单独的做法的几乎的工作。这是白盒密码,而到今天为止,没有人想出了一个真正安全的解决方案,这一类的问题。你至少可以做的仍然是发行为每个用户一个键,就可以禁止虐待键。

If you are trying to keep other software vendors from getting your API key to prevent the development of alternate clients, only the encrypt-and-store-seperately approach almost works. This is whitebox crypto, and to date, no one has come up with a truly secure solution to problems of this class. The least you can do is still issue a single key for each user so you can ban abused keys.

(*)编辑: SSL连接应该不再被视为没有的 = http://filippo.io/Heartbleed/#stackoverflow.com\">taking额外步骤来验证他们。

(*) SSL connections should no longer be considered secure without taking additional steps to verify them.

这篇关于基于令牌的REST API认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆