121

Bob uses a web application in order to achieve something. And:

  • His browser is on diet, therefore it does not support cookies.
  • The web application is a popular one, it deals with a lot of users at a given moment - it has to scale well. As long as keeping session would impose a limit to the number of simultaneous connections, and, of course, will bring a non-negligible performance penalty, we might like to have a session-less system :)

Some important notes:

  • we do have transport security (HTTPS and its best friends);
  • behind the curtains, the web application delegates a lot of operations to external services, on current user's behalf (those systems do recognize Bob as one of their users) - this means that we have to forward them Bob's credentials.

Now, how do we authenticate Bob (on each and every request)? Which would be a reasonable way to implement such a thing?

  • playing tennis with the credentials via HTML form hidden fields... the ball contains the credentials (username & password) and the two rackets are the browser and the web application respectively. In other words, we may transport data back and forth via form fields instead of via cookies. At each web request, the browser posts the credentials. Though, in the case of a single-page application, this may look like playing squash against a rubber wall, instead of playing tennis, as the web form containing the credentials might be kept alive the entire lifetime of the web page (and the server will be configured not to offer the credentials back).
  • storing the username & the password in the context of the page - JavaScript variables etc. Single-page required here, IMHO.
  • encrypted token - based authentication. In this case, the log-in action would result in the generation of an encrypted security token (username + password + something else). This token would be served back to the client and the upcoming requests will be accompanied by the token. Does this make sense? We already have HTTPS...
  • others...
  • last resort: do not do this, store credentials in the session! Session is good. With or without cookies.

Does any web / security concern come into your mind, regarding any of the previously described ideas? For example,

  • time-outing - we may keep a timestamp, along with the credentials (time-stamp = the time Bob entered his credentials). E.g. when NOW - timestamp > threshold, we might deny the request.
  • Cross-site scripting protection - should not be different in any way, right?

Thank you a lot for taking the time to reading this :)

4

2 回答 2

79

啊,我喜欢这些问题——在没有会话的情况下保持会话。

在我的申请评估期间,我已经看到了多种方法来做到这一点。一种流行的方式是您提到的打网球方式 - 在每个请求中发送用户名和密码以验证用户。在我看来,这是不安全的,尤其是在应用程序不是单页的情况下。它也是不可扩展的,特别是如果您想在将来除了身份验证之外还想为您的应用程序添加授权(尽管我猜您也可以基于登录构建一些东西)

一种流行的,虽然不是完全无状态的机制(假设你有 JavaScript 执行)是在 JavaScript 中嵌入会话 cookie。我内心的安全人员对此大喊大叫,但它实际上可以工作 - 每个请求都有一个X-Authentication-Token标头或类似的东西,然后将其映射到后端的数据库,内存中的文件存储等以验证用户。这个令牌可以有你指定的任何时间的超时,如果超时,用户必须重新登录。它具有相当的可扩展性——如果你将它存储在数据库中,执行它的一个 SQL 语句,并且使用正确的索引,它应该花费很少的时间来执行,即使有多个同时用户。不过,这里的负载测试肯定会有所帮助。如果我正确阅读了问题,这将是您的加密令牌机制-尽管,我强烈建议您使用 32 个字符的加密随机令牌,而不是使用用户名 + 密码 + 其他任何东西的组合 - 这样,它就会保持不可预测,但您仍然可以将其与用户 ID 或类似的东西相关联。

无论您最终使用哪个,请确保将其安全地发送给您。HTTPS 可以通过网络保护您,但如果您通过 URL 泄漏会话令牌(或更糟糕的是,通过 URL 泄漏凭据),它不会保护您。我建议使用标头,或者如果这不可行,则每次都通过 POST 请求发送令牌(这意味着用户浏览器上的隐藏表单字段。)使用 POST 请求的后一种方法应该使用 CSRF 防御,只是以防万一,尽管我怀疑使用令牌本身可能是某种 CSRF 防御。

最后但并非最不重要的一点是,确保您在后端有一些机制来清除过期的令牌。这是过去许多应用程序的祸根——一个快速增长的身份验证令牌数据库,似乎永远不会消失。如果您需要支持多用户登录,请确保限制数量,或者对每个令牌设置更短的时间限制。正如我之前所说,负载测试可能是这个问题的答案。

我还可以想到其他一些安全问题,但它们太宽泛,无法在现阶段解决 - 如果您牢记所有使用(和滥用)案例,您应该能够很好地实现这个系统。

于 2013-12-19T06:31:38.123 回答
1

关于登录选项 - 我认为通常您也希望为来宾支持会话。

因此,如果您想强制登录,加密令牌选项可能会很好。不知何故,它也可能对来宾会议有好处。在另一个方向上,我会在将令牌附加到 URL 和网球选项之间结合起来。

请注意,仅在 URL 中发送凭据可能很危险。例如,您可能会通过 HTTP 引用标头甚至只是检查您的流量或监视您的计算机的人泄漏令牌。

另一件事,即使您可以使用 cookie,我也建议您添加随机令牌或随机验证程序,以保护自己免受跨站请求伪造 (CSRF) 攻击。

于 2013-12-15T09:19:20.003 回答