REST Web 服务身份验证令牌实现 [英] REST Web Service authentication token implementation

查看:44
本文介绍了REST Web 服务身份验证令牌实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 C# 实现 REST Web 服务,该服务将作为云服务托管在 Azure 上.由于它是 REST 服务,因此它是无状态的,因此没有 cookie 或会话状态.

I'm implementing a REST web service using C# which will be hosted on Azure as a cloud service. Since it is a REST service, it is stateless and therefore no cookies or session states.

Web 服务只能通过 HTTPS(由 StartSSL.com 提供的证书)访问.

The web service can only be accessed over HTTPS (Certificate provided by StartSSL.com).

用户成功登录服务后,他们将获得一个安全令牌.此令牌将在未来的通信中提供身份验证.

Upon a user successfully logging into the service they will get a security token. This token will provide authentication in future communications.

令牌将包含客户端的时间戳、用户 ID 和 IP 地址.

The token will contain a timestamp, userid and ip address of the client.

所有通信都将仅通过 HTTPS 进行,因此我不担心令牌被拦截并用于重放攻击;无论如何,令牌都会过期.

All communication will only happen over HTTPS so I'm not concerned about the token being intercepted and used in replay attacks; the token will have an expiry anyway.

由于这是一项面向公众的服务,但我担心有人可能会注册该服务、登录并修改他们收到的令牌以访问其他用户的帐户.

Since this is a public facing service I am however concerned that someone could register with the service, login and then modifying the token that they receive to access the accounts of other users.

我想知道如何最好地保护令牌的内容并验证它没有被篡改.

I'm wondering how best to secure the content of the token and also verify that it hasn't been tampered with.

我计划执行以下操作来保护令牌:

I plan on doing the following to secure the token:

客户端成功登录服务,服务成功:

The client successfully logs into the service and the service does:

  1. 生成一个随机值并使用 SHA256 对其进行 1000 次散列.
  2. 从私钥 + 散列随机值生成一次性会话密钥.
  3. 使用 SHA256 将会话密钥散列 1000 次,然后使用它来加密令牌
  4. 使用私钥通过 RSA 对加密令牌进行签名.
  5. 以未加密的 JSON 包将加密的令牌 + 签名 + 散列的随机值发送给客户端.

当客户端调用服务时,它会将加密的令牌和签名在未加密的 JSON 包中发送到服务.该服务将

When the client calls a service it sends the encrypted token and signature in an unencrypted JSON package to the service. The service will

  1. 从私钥+散列的随机值重新创建会话密钥
  2. 使用私钥验证签名
  3. 使用散列的会话密钥解密令牌
  4. 检查令牌是否未过期
  5. 继续请求的操作...

我对加密一无所知,所以我有一些问题:

I don't really know anything about encryption so I have some questions:

  1. 这是否足够了,还是太过分了?
  2. 我读到为了检测篡改,我应该在令牌中包含一个 HMAC.既然我是用私钥签名的,我还需要 HMAC 吗?
  3. 我应该使用 Rijndael 而不是 RSA?
  4. 如果首选 Rijndael,生成的 IV 是否需要解密?即我可以扔掉它还是我需要将加密的令牌发送给它?例如加密令牌 + HMAC + IV + 散列随机值.

由于所有通信都通过 HTTPS 进行,因此未加密的 JSON 包在到达客户端之前并不是真正未加密的.

Since all communication happens over HTTPS the unencrypted JSON package isn't really unencrypted until it reaches the client.

此外,我可能想稍后在 PHP 中重新实现该服务,因此这一切也需要在 PHP 中实现.

Also I may want to re-implement the service in PHP later so this all needs to be doable in PHP as well.

感谢您的帮助

推荐答案

你真的想太多了.说实话,最好的令牌安全性依赖于随机性,或者更准确地说是不可预测性.最好的代币是完全随机的.您是对的,担心用户会修改他/她的令牌并使用它来访问其他人的帐户.这是一种常见的攻击,称为会话窃取".当令牌在服务器端随机生成并过期时,这种攻击几乎是不可能的.使用用户的信息(如 IP 和/或时间戳)是不好的做法,因为它提高了可预测性.我在大学里做过一次攻击,成功猜出了基于服务器时间戳的活动令牌(以微秒为单位).该应用程序的作者认为微秒的变化速度会快到无法预测,但事实并非如此.

You are really over-thinking the token. Truthfully, the best token security relies on randomness, or more accurately unpredictability. The best tokens are completely random. You are right that a concern is that a user will modify his/her token and use it to access the accounts of others. This is a common attack known as "session stealing." This attack is nearly impossible when the tokens are randomly generated and expired on the server side. Using the user's information such as IP and/or a time stamp is bad practice because it improves predictability. I did an attack in college that successfully guessed active tokens that were based on server time stamps in microseconds. The author of the application thought microseconds would change fast enough that they'd be unpredictable, but that was not the case.

您应该知道,当用户位于代理服务器后面时,代理有时会以纯文本形式查看他们的 SSL 请求(出于安全原因,许多代理会执行深度数据包检查).出于这个原因,您最好让会话过期.如果您不这样做,您的用户将很容易受到此类攻击,并且还可能遭受 XSS 和 CSRF.

You should be aware that when users are behind proxy servers, the proxy will sometimes view their SSL requests in plain text (for security reasons, many proxies will perform deep packet inspection). For this reason it is good that you expire the sessions. If you didn't your users would be vulnerable to an attack such as this, and also possible XSS and CSRF.

RSA 或 Rijndael 应该足够了,只要提供合理的密钥长度.此外,您应该使用带有令牌的 HMAC 来防止篡改,即使您正在对其进行签名.从理论上讲,这将是多余的,因为您使用私钥进行签名.但是,HMAC 已经过很好的测试,您对签名机制的实现可能存在缺陷.因此,最好使用 HMAC.您会惊讶地发现,有多少自己动手"的安全实现存在缺陷,导致它们受到威胁.

RSA or Rijndael should be plenty sufficient, provided a reasonable key length. Also, you should use an HMAC with the token to prevent tampering, even if you're signing it. In theory it would be redundant, since you're signing with a private key. However, HMAC is very well tested, and your implementation of the signing mechanism could be flawed. For that reason it is better to use HMAC. You'd be surprised how many "roll your own" security implementations have flaws that lead them to compromise.

你听起来很了解安全.保持良好的工作!在这个世界上,我们需要更多具有安全意识的开发人员.

You sound pretty savvy on security. Keep up the good work! We need more security conscious devs in this world.

在令牌中包含时间戳/用户 ID 被认为是安全的,只要它们使用强对称秘密密钥(如 AES、Blowfish 等)加密,只有服务器拥有并且作为只要令牌包含一个防篡改哈希,例如 HMAC,使用密钥和用户 ID/时间戳进行加密.散列保证完整性,加密保证机密性.

It is considered safe to include timestamps/user IDs in the token as long as they are encrypted with a strong symmetric secret key (like AES, Blowfish, etc) that only the server has and as long as the token includes a tamper-proof hash with it such as HMAC, which is encrypted with the secret key along with the user ID/timestamp. The hash guarantees integrity, and the encryption guarantees confidentiality.

如果您没有在加密中包含 HMAC(或其他哈希),则用户可能会篡改加密令牌并将其解密为有效的内容.我对服务器进行了一次攻击,其中用户 ID 和时间戳被加密并用作没有散列的令牌.通过更改字符串中的一个随机字符,我能够将我的用户 ID 从 58762 之类的内容更改为 58531.虽然我无法选择新"用户 ID,但我能够访问其他人的帐户(这是在学术界,作为课程的一部分).

If you don't include the HMAC (or other hash) in the encryption, then it is possible for users to tamper with the encrypted token and have it decrypt to something valid. I did an attack on a server in which the User ID and time stamp were encrypted and used as a token without a hash. By changing one random character in the string, I was able to change my user ID from something like 58762 to 58531. While I couldn't pick the "new" user ID, I was able to access someone else's account (this was in academia, as part of a course).

另一种方法是使用完全随机的令牌值,并在服务器端将其映射到存储的用户 ID/时间戳(保留在服务器端,因此不受客户端控制).这需要更多的内存和处理能力,但更安全.这是您必须根据具体情况做出的决定.

An alternative to this is to use a completely random token value, and map it on the server side to the stored User ID/time stamp (which stays on the server side and is thus outside of the clients control). This takes a little more memory and processing power, but is more secure. This is a decision you'll have to make on a case by case basis.

至于从 IV 和其他密钥重用/派生密钥,这通常是可以的,前提是这些密钥仅在短时间内有效.从数学上讲,不太可能有人可以打破它们.然而这是可能的.如果您想走偏执路线(我通常会这样做),请随机生成所有新密钥.

As for reusing/deriving keys from the IV and other keys, this is usually ok, provided that the keys are only valid for a short period of time. Mathematically it is unlikely someone can break them. It is possible however. If you want to go the paranoid route (which I usually do), generate all new keys randomly.

这篇关于REST Web 服务身份验证令牌实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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