【问题标题】:What's the best way to use HTTP Authentication in an Ajax Application that's not 100% AJAX在不是 100% AJAX 的 Ajax 应用程序中使用 HTTP 身份验证的最佳方式是什么
【发布时间】:2012-02-26 08:58:11
【问题描述】:

我有一个标准的 HTML 登录页面,我更愿意使用它而不是浏览器提供的标准 HTTP 身份验证弹出窗口。今天,我正在使用会话cookie来跟踪登录后的会话,但我希望是无状态的并且每次都通过HTTP身份验证。我打的网络服务已经支持这个,所以这是一个浏览器的问题。

在 jQuery 中添加身份验证凭据很简单,但我不知道如何保留它们。如果您从登录页面(一个 jsp)转到主页(另一个 jsp),您显然不会保留登录页面中的用户名和密码字段。我知道如果您从弹出窗口中输入它们,某些浏览器会存储您的 HTTP 身份验证凭据,但我不知道它们是否在使用 XHRRequest 时被存储。如果有,浏览器之间是否有很多一致性?

此外,用户还需要能够“退出”应用程序。如果浏览器存储了身份验证凭据,有没有办法使用 JavaScript 清除它们。

我觉得我不能成为第一个尝试解决这个问题的人。是否有一些 jQuery 插件或已经处理这个问题的东西?还是根本不可能做我想做的事?

【问题讨论】:

    标签: ajax jquery xmlhttprequest http-authentication stateless-session


    【解决方案1】:

    你有两个选择:

    1) 凭据的客户端存储——这不是一个好主意。出于显而易见的原因,您不想将用户名/密码存储在客户端上。如果您有密码的哈希版本,它可能不会那么糟糕,但仍然不推荐。在任何情况下,如果您要在客户端存储,您要么必须使用 cookie,要么使用 HTML5 local storage(尚未得到广泛支持)

    2) 凭据的服务器端存储——通常通过会话完成。然后可以将生成的 Session ID 传递回客户端并保存在 cookie 或每个后续 AJAX 调用的 URL 中(例如?SESSID=xyz

    服务器端方法将是最安全、最可靠且最容易实施的方法

    【讨论】:

    • HTML5本地存储没有被广泛支持是真的吗?我知道的所有主要浏览器都有支持它的版本。你的意思是那些版本的浏览器还没有大量用户吗?
    • 无论如何,我知道如何在服务器上创建会话。我试图避免在服务器上进行会话,并让我的服务器真正无状态。
    • 没有得到广泛支持,我的意思是你不能依赖野外的支持。诚然,大多数(如果不是全部)现代浏览器都支持它,但在野外,您的用户不一定会使用最新的浏览器。如果您有一个受控的目标受众,您可能需要兼容的浏览器,那么本地存储可能是您的答案。
    • 还有一个问题:如果浏览器提示我输入用户名和密码,它会将它们存储在某个地方(至少在内存中)。将凭据添加到 XHRRequest 是否会将这些凭据存储在同一个位置?如果是这样,除了在退出时删除它们之外,这解决了我的问题。
    • 我不确定,但对我来说它对 XHR 请求的工作方式似乎是合乎逻辑的。这些可能对您有帮助:hc.apache.org/httpcomponents-client-ga/tutorial/html/…opensourcesmall.biz/2008/06/technical-note-http-auth-with-ajax
    【解决方案2】:

    好的,我会尽力帮助...

    首先,了解 HTTP 身份验证的工作原理。有两个版本 - Basic 和 Digest。基本以明文传输,摘要加密。使用这些类型的身份验证,用户名/密码在每个请求的 HTTP 标头中传递。浏览器在登录时捕获这些信息,并将它们存储在不可访问的浏览器会话 cookie 中,当浏览器会话关闭时,该 cookie 将被删除。因此,在回答您的一个问题时,您无法从 javascript 访问这些内容。

    您可以为用户名和密码创建自己的会话 cookie 变量。用于此的 jQuery 函数非常简单。请参阅 jquery-cookie 模块作为如何设置会话 cookie 的示例。这些可以从会话 cookie 中检索并与每个 ajax 请求一起发送并在服务器中进行验证。然而,这并不是一种特别好的身份验证方式,因为嗅探网络将允许任何人轻松获取您的身份验证详细信息。但是,它会起作用。

    使用基于会话 cookie 的身份验证(其中会话 ID 随每个请求一起发送)是执行此操作的最佳方式。在服务器端,您需要为每个 HTTP 请求调用一个函数。此函数应执行以下操作:

       check to see if the session has been authenticated
       if no:
           redirect to login screen
       if yes:
           do authorization and allow the user access to the page
    

    大多数 Web 框架都支持会话 cookie 身份验证和服务器上的会话 ID 管理。这绝对是要走的路。

    【讨论】:

      【解决方案3】:

      这很有趣。

      使用 cookie 管理服务器上的用户会话。当用户第一次访问登录页面时创建一个会话,并通过响应将会话 id/key 作为值传递给其中一个 cookie。当用户通过身份验证时,将用户“密钥”信息放入 cookie 中,将“值”放入服务器的应用程序上下文中。用户登录后,任何后续请求都将根据服务器上的会话 cookie 值进行身份验证。授权将根据作为 cookie 值传递的用户“密钥”进行。

      注销时从服务器清除基于会话的 cookie 并将站点刷新到默认页面。

      Cookie 在不同的浏览器中很奇怪 - 只是一个注释;)

      希望这会有所帮助。

      【讨论】:

      • 我试图完全避免任何服务器会话。我认为使用 Web 应用程序执行此操作的唯一方法是在每个请求中发送身份验证并将身份验证信息存储在浏览器状态,而不是服务器状态。但是,我不知道在浏览器状态下存储身份验证的最佳方式。
      • 在浏览器上存储身份验证会导致安全漏洞。 HTML5 确实支持数据库,但它们可以破解吗?旧版本的浏览器中不存在 HTML5,您的客户可能并不总是拥有最新版本。使用 IE 总是很“有趣” :-)
      • 这不是存储状态的唯一地方。浏览器存储您的 HTTP 基本身份验证凭据的任何缓存都存在。有 cookie,只要 cookie 具有身份验证所需的所有信息。 (我的意思是真正的身份验证,不匹配已经过身份验证的服务器会话。)
      • 对每个请求运行身份验证会变得非常密集?
      • 不像每个用户都必须有一个内存会话那么密集。
      【解决方案4】:

      更新

      下面的答案发布于 2012 年,链接大多已失效。但是,从那时起,使用JSON Web Tokens 出现了针对同一解决方案的更优雅的基于标准的方法。这是good blog post 解释如何使用它们。


      大多数答案都没有抓住重点,即避免进行任何服务器端会话。我不希望服务器中有任何应用程序状态。我将奖励最接近的答案,但真正的功劳归功于 rest-discuss groupJon Moore 的正确答案以及帮助我​​真正理解它的 Mike Amundsen

      我得到的最佳答案是使用 cookie,但不是大多数应用程序服务器提供给您的典型自动会话 id cookie。 cookie(将随每个后续请求自动发送)是服务器签名的用户标识符和时间。您可以在 cookie 中包含过期时间,以便它模拟服务器上典型的 30 分钟会话(这意味着您必须通过后续请求将其向前推进),并防止相同的 cookie 永远有效。

      XHR/AJAX 部分是红鲱鱼。无论您是在执行 XHR 请求还是老式的逐页 Web 应用程序,这都将起作用。要点是:

      • cookie 会在后续请求中自动发送,因此没有 需要特殊的脚本 - 这就是浏览器的工作方式。
      • 服务器不需要为用户存储任何会话,所以用户 可以访问集群中的任何服务器,而无需重新进行身份验证。

      【讨论】:

      • 链接不再起作用...有机会获得更多详细信息吗?
      • 我已经更新了我的答案。自首次发布以来,情况发生了很大变化。
      【解决方案5】:

      有点有趣的是,您考虑将一些 authent 推送给客户端。如果您想要一个传统的解决方案,KOGI 的服务器端建议是可行的方法。

      但是您似乎也在询问有关涉及用户提供的机密的内存泄漏的问题。好问题。但是为了回答这个问题,我会说它必须是特定于浏览器的。它是浏览器内部结构、javascript 引擎内部结构 - 取决于客户端应用程序(即浏览器或浏览器中的 js)存储用户输入值的位置。

      这些值很可能不会在整个内存中不必要地复制,但无法保证这一点。除了负责任的 javascript 编码实践之外,您无法保证用户输入位置的限制。

      题外话

      基本的一点是,如果您将其存储在客户端上,它并不是真正安全的——除非服务器使用只有服务器(或用户通过其正确凭据)拥有的密钥将加密信息存储在客户端上。因此,您可以想象编写一个 JS 应用程序来在客户端上进行一些身份验证——这与银行卡(过去?)通过检查卡上的 PIN 而不是返回 DB 来进行 POS 身份验证非常相似。它基于(有点脆弱)假设用户没有对客户端上的“暗区”cookie/本地存储/银行卡上的磁条的直接读/写访问权限。因此,我只建议将其作为虚假身份的取消资格,而不是作为凭证的唯一资格。

      要点

      如果您确实想要无状态,只需将用户凭据存储在本地存储中,或者作为 cookie 存储,但使用服务器密钥对其进行加密。当您需要它们通过 HTTPS 向服务器发送带有加密/使用存储凭据的 XHR 时,让您的服务器解密它们并将它们发送到回调。然后通过 HTTPS 的明文进行身份验证。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-10
        • 1970-01-01
        • 2020-03-27
        • 1970-01-01
        相关资源
        最近更新 更多