5

我写了一个 RESTful servlet,UI 开发人员希望将登录状态保存在服务器上。

他提出了一个奇怪的说法:“我还没有遇到过纯 REST 的生产 REST 实现。我见过的都是让服务器维护会话。”

我觉得这很难接受。首先,技术上存在大量纯 HTTP 页面,全都是纯 RESTful 的。其次,是的,有标记为 RESTful 的非 RESTful 实现,就像标记为“黄金”的黄铜一样。第三,仅仅因为其他人跳下桥并不意味着我应该。

背景:它是一个使用 HTTPS 和基本身份验证的 JavaScript Ajax Web 应用程序。为避免出现通常的(不可自定义的)浏览器登录弹出框,应用程序会显示一个登录屏幕,其中包含产品徽标以及名称和密码的文本框。名称和密码存储在文档中,并在每个请求的 Authorization 标头中发送。如果刷新页面,名称和密码将丢失,用户必须再次输入。这被认为是一个错误;UI 开发人员希望能够在不再次输入密码的情况下按下刷新按钮。

所以开发者想要使用cookie 或JSP 会话。Abby,最终每个 REST 实现都会在服务器上维护应用程序状态,这是真的吗?或者有什么方法可以解决这个问题并且仍然保持我的 RESTful 纯度?

4

4 回答 4

3

我认为出于实际原因(主要是可浏览能力),您需要区分application stateauthentication state。我想不出任何不会在服务器端保留某种形式的状态的身份验证机制。

真正重要的是它与应用程序的分离程度。例如,HTTP Digest 在服务器上保留了某种形式的状态,但这显然被抽象为正常WWW-AuthenticateAuthorization标头协商的一部分。因为大多数浏览器本身都支持它,所以这与应用程序正交,因此不会破坏 REST 的无状态原则。

如今,由于用户对 HTTP Basic/Digest 身份验证在浏览器中不满足的审美期望,网站倾向于使用基于表单的身份验证,随后使用 cookie。公平地说,这不仅仅是它的外观,它还涉及可用性(例如“忘记密码”信息,尽管这可能在 401 响应的正文中)和安全性。浏览器不允许您轻松地从 Basic/Digest/Certificate 身份验证中注销,除非它完全在单个页面中的 Ajax 中完成,正如您所提到的,这可以帮助 CSRF。

我认为 cookie 可以用于身份验证,但请确保不要在会话中存储与应用程序相关的变量。

您可以阅读Roy Fielding 关于该主题的一些评论

身份验证是正交的。当 Cookie 仅用于内容协商或身份验证时,它们也是正交的。但是,在 REST 中不允许使用 Cookie 身份验证,因为它缺乏可见性,这会导致安全问题,因为其他组件不知道它是敏感信息。

编辑(关于安全方面的进一步评论):

我意识到 Roy Fielding 在我引用的消息中的评论是出于安全原因反对 cookie。他当然是对的。然而,在我看来,通过 Basic/Digest/Cert (在 2003 年,该消息的日期并没有真正引起注意)来防止 CSRF 比防止 cookie 盗窃更难。当然,这取决于实施。没有完美的解决方案,但如果您使用 cookie,请通过 HTTPS 使用安全 cookie。

于 2010-06-25T16:16:17.467 回答
2

我认为使用 cookie 在客户端维护此信息没有问题。Cookie 仅在用作指向某些服务器端会话状态的指针时才会成为问题。

您需要关注的主要是 cookie 中信息的安全性。您可能不想将明文密码放入 cookie 中 :-)

于 2010-06-25T16:01:35.880 回答
0
  • 默认情况下,当您刷新页面时,浏览器不会再次要求提供凭据。您可能需要对此进行调查,因为如果您解决了这个问题,那么您的问题就解决了。
  • 您可以在大多数情况下维护 REST 服务,但用户可以使用 HTTP 或 cookie 进行身份验证。即,如果您没有 cookie,该服务也可以工作。

问候,

艾比。

于 2010-06-25T16:03:14.547 回答
0

如果您在身份验证后返回某种会话 ID 并在每次调用中传递它,这与在每次调用中传递身份验证凭据并没有太大区别。在性能方面,后者仍然可以缓存凭据,因此不会影响性能。在安全性方面,不必保留凭据更好,因为会话过期但凭据(通常)不会过期。可以说,避免会话更加健壮,因为服务器可以忘记调用之间的所有内容但仍然可以工作。

简而言之,在这两个方向上都没有压倒性的有力论据,而且您可能不应该对您对 REST 的承诺是否足够“纯粹”而挂断电话。真正的问题是客户的行为,正如 Sjoerd 所建议的那样,这是您可以独立调整的东西。

于 2010-06-25T16:09:39.620 回答