16

我们正在开发一个新项目,我们是两个主要开发人员,并且在如何使用令牌来保护服务器和客户端之间的通信方面处于十字路口:

第一个建议:

步骤一)客户端请求一个主令牌,通过将用户名和密码以及current_time(这个变量将保存在服务器的数据库和客户端中)到api,服务器解释输入,并呈现一个哈希令牌(例如:58f52c075aca5d3e07869598c4d66648)将其保存在数据库中并返回给客户端。

第二步)客户端现在保存主令牌,并使用主令牌 + 在身份验证请求中发送的 current_time 变量创建新的哈希令牌(让我们将此新令牌称为 main_token),服务器也这样做并使用创建相同的令牌相同的算法。

第三步)客户端每次查询服务端API,都会发送main_token给服务端,此时服务端将生成的token与客户端发送的main_token进行比较,如果匹配,则说明用户是真实的

第二个建议:

第一步) 客户端生成两个随机密钥 ($key1 = rand(10000,90000); $key2 = rand(10000,90000);) 对于 API 上的每个请求,客户端使用查询类型创建哈希,然后具有复杂算法的两个密钥,并将这两个密钥 + 哈希发送到服务器

第二步)服务器使用客户端使用的相同算法创建一个哈希值,并与客户端发送的哈希值进行比较,如果匹配,服务器继续处理查询


现在,问题是,哪一种是用于保护 api 请求的最合乎逻辑、最安全的方式

此致

4

4 回答 4

12

这两种解决方案都对安全性没有任何好处。

第一个建议

一旦我有了 main_token,我就可以计算任何散列(main_token + 时间戳)。我只需要访问 API 就是 main_token,那么为什么还要麻烦时间戳业务呢?

第二个建议

如果您为每个请求和查询类型发送两个随机数,那么是什么阻止我这样做并使用您的 API?算法?密码算法的规则是,如果你自己滚动,有人会破解它。第二条规则是默默无闻的安全性不起作用。

如果您的身份验证过程比您的 api 更安全,您可以用不同的方式保护调用:

身份验证阶段 (SSL)

  1. 客户端发送用户/密码并获得一个随机字符串“Secret_token”。
  2. Secret_token 存储在客户端和服务器端。
  3. Secret_token 永远不会再次通过网络传输。

API 请求阶段

  1. 客户端创建请求
  2. 客户端规范化请求
  3. 客户端使用 Secret_token 计算规范化请求的签名*
  4. 客户端将请求+签名发送到服务器
  5. 服务器规范化请求
  6. 服务器使用 Secret_token 计算规范化请求的签名
  7. 如果签名匹配,服务器继续请求

计算签名

首先,规范化请求。这可能意味着提取包括方法(post、get、action、timestamp)在内的重要参数并将它们按顺序排列。然后通过以 Secret_token 作为参数的 HMAC 算法运行该字符串。

分析

Secret_token 仅在身份验证发生时通过线路传输一次。假设身份验证过程非常安全(因为在此过程中传输密码,这是一个安全的假设)。

注意:通过明文发送仍然不安全,请使用 SSL。

HMAC 是众所周知的解决方案。看:

于 2013-07-28T19:13:02.110 回答
7

为什么不在每个请求上都使用标准HTTP Auth,所以每次都通过用户名和密码。然后服务器只是针对该用户名/密码组合而不是令牌进行验证。

鉴于您正在使用 SSL/TLS 进行连接,因此不存在用户名/密码被暴露的风险。并且也没有对 SSL 进行重放攻击的可能性,因此不需要过期任何东西。

我建议保持简单并使用已经开发的现有协议。在安全方面,除非您有真正令人信服的理由,否则您可能不应该尝试重新发明轮子。

于 2013-07-21T22:57:23.470 回答
5

首先一些观察

  1. 在第一种方法中,令牌本质上变成了一个长期有效的密码。每个请求都会重复使用它。所以,如果这个令牌被泄露,你就完成了。并不是说不鼓励这样做,因为 OAuth 2 正是这样做的,但 SSL 在这里绝对是强制性的。此外,如果您这样做,您必须确保令牌具有到期日期和确保在出现妥协时迅速撤销令牌的机制。

  2. 您描述的第二个选项类似于 AWS 使用的选项,但没有密钥。这里的优点是,由于它使用查询生成散列,因此散列将随每个请求而改变。因此,如果一个令牌被泄露,您不必担心,因为它不适用于任何其他请求。此外,您始终可以使用这种方法检测中间人攻击,因为如果内容被修改,算法将生成不匹配的哈希。

这两种方法都是有效的并且被广泛使用。所以,如果你不想要 SSL,那么 2 是要走的路。如果您对 SSL 没问题,那么 OAuth 是另一种选择。我推荐的实际上是使用其中任何一个中的既定技术。如果您使用 1) 然后查看 Oauth2,如果您使用 2) 然后坚持使用 AWS 方案(严格来说,这不是一个标准,但它被广泛记录)。

我认为一些链接可能会有所帮助

http://www.wolfe.id.au/2012/10/20/what-is-hmac-and-why-is-it-useful/

http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/

http://blog.cloudfoundry.com/2012/10/09/securing-restful-web-services-with-oauth2/

于 2013-07-22T16:31:43.427 回答
0

由于客户端具有计算第一个建议中的第二个令牌所需的所有信息,因此第二个令牌并不比第一个令牌更好(更安全,更安全)。第二个建议似乎是预共享密钥的一些变体。这些中的任何一个都可能是足够的安全措施。就个人而言,我更喜欢第一种方法,并且一直使用 SSL。将令牌想象成用户名和密码的替代品,您会在每个请求中发送令牌明文吗?(许多网站正是这样做的。)

于 2013-07-18T22:59:02.070 回答