如何做无状态(无会话)&无 cookie 身份验证? [英] How to do stateless (session-less) & cookie-less authentication?

查看:27
本文介绍了如何做无状态(无会话)&无 cookie 身份验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Bob 使用 Web 应用程序来实现某些目标.并且:

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

  • 他的浏览器正在节食,因此不支持cookies.
  • Web 应用程序是一种流行的应用程序,它在特定时刻处理大量用户 - 它必须扩展.只要保持会话会限制同时连接的数量,当然还会带来不可忽视的性能损失,我们可能希望有一个无会话系统:)
  • 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 :)

一些重要的注意事项:

  • 我们确实有传输安全(HTTPS 及其最好的朋友);
  • 幕后,Web 应用程序将许多操作委托给外部服务,代表当前用户(这些系统确实将 Bob 识别为他们的用户之一)-这意味着我们必须向他们转发 Bob 的凭据.
  • 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.

现在,我们如何验证 Bob(在每个请求上)?实现这种事情的合理方法是什么?

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

  • 通过HTML 表单隐藏字段使用凭据打网球...包含凭据(用户名和密码)) 和两个球拍分别是浏览器和网络应用程序.换句话说,我们可能会通过表单字段而不是通过 cookie 来回传输数据.在每个 Web 请求中,浏览器都会发布凭据.不过,在单页应用程序的情况下,这可能看起来像对着橡胶墙玩壁球,而不是玩网球,因为包含凭据的网络表单可能会在网页的整个生命周期内保持活动状态(并且服务器将被配置为不提供凭据).
  • 存储用户名 &页面上下文中的密码 - JavaScript 变量等.此处需要单页,恕我直言.
  • 基于加密令牌的身份验证.在这种情况下,登录操作将导致生成加密的安全令牌(用户名 + 密码 + 其他内容).该令牌将返回给客户端,即将到来的请求将伴随该令牌.这有意义吗?我们已经有了 HTTPS...
  • 其他...
  • 最后的手段:不要这样做,在会话中存储凭据!会话很好.有或没有 cookie.
  • 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,

  • 超时 - 我们可能会保留一个时间戳以及凭据(时间戳 = Bob 输入凭据的时间).例如.当NOW - timestamp > threshold时,我们可能会拒绝请求.
  • 跨站点脚本保护 - 应该不会有任何不同,对吗?
  • 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 :)

推荐答案

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

Ah, I love these questions - maintaining a session without a session.

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

I've seen multiple ways to do this during my stints during application assessments. One of the popular ways is the playing tennis way that you mentioned - sending the username and password in every request to authenticate the user. This, in my opinion, is unsafe, especially if the application isn't single page. It is also not scalable, especially if you want to add authorization to your app in addition to authentication in the future (although I guess you could build something based on logins too)

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

One popular, although not completely stateless mechanism (assuming you have JavaScript execution) is to embed the session cookie in the JavaScript. The security guy in me is screaming at this, but it could actually work - every request has a X-Authentication-Token header or something like that, and you map that to a database, file-store in memory, etc. on the backend to validate the user. This token can have a timeout of whatever time you specified, and if it times out, the user has to log in again. It's fairly scalable - if you store it in a database, its one SQL statement executed, and with the correct indexes, it should take very little time to execute, even with multiple simultaneous users. Load testing here would definitely help though. If I read the question correctly, this would be your encrypted token mechanism - although, I would strongly suggest that you use a cryptographically random token of say 32 characters, versus using a combination of username + password + whatever else - this way, it stays unpredictable, but you can still associate it with the user ID or some such thing.

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

Whichever you do end up using, ensure it is sent to you safely. HTTPS protects you across the wire, but it doesn't protect you if you leak the session token via the URL (or worse, credentials via the URL). I would recommend using a header, or if that's not feasible, sending the token via a POST request every time (this would mean a hidden form field on the user's browser.) The latter approach of using a POST request should use CSRF defenses, just in case, though I suspect using the token itself might be some sort of a CSRF defense.

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

Last, but not the least, make sure you have some mechanism in the backend to purge expired tokens. This has been the bane of many applications in the past - a rapidly growing database of authentication tokens which never seems to go away. If you need to support multiple user logins, make sure you either limit the number, or have a shorter time limit on each token. As I said before, load testing may be the answer to this.

还有一些其他的安全问题我能想到,但它们太广泛了,在这个阶段无法解决 - 如果你牢记所有使用(和滥用)的情况,你应该能够做一个公平的该系统的良好实施.

There are some other security concerns that I can think of, but they are too broad to be addressed at this stage - if you keep all the use (and abuse) cases in mind, you should probably be able to do a fairly good implementation of this system.

这篇关于如何做无状态(无会话)&无 cookie 身份验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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