你能帮我理解这个吗? “常见的 REST 错误:会话无关紧要”

Posted

技术标签:

【中文标题】你能帮我理解这个吗? “常见的 REST 错误:会话无关紧要”【英文标题】:Can you help me understand this? "Common REST Mistakes: Sessions are irrelevant" 【发布时间】:2010-10-07 08:47:05 【问题描述】:

免责声明:我是 REST 思想流派的新手,我正在努力思考它。

所以,我正在阅读这个页面,Common REST Mistakes,我发现我完全被与会话无关的部分所困惑。页面是这样写的:

应该不需要客户 “登录”或“开始连接”。 HTTP 身份验证完成 自动在每条消息上。客户 应用程序是消费者 资源,而不是服务。所以 没有什么可以登录的!让我们 假设您正在预订航班 REST 网络服务。你不创建一个 新的“会话”连接到 服务。而是你问“行程 创建者对象”为您创建一个新的 行程。你可以开始填写 空白,然后完全得到一些 其他地方的不同组件 网络来填补一些其他的空白。 没有会话所以没有 迁移会话状态的问题 客户之间。也没有 中的“会话亲和力”问题 服务器(虽然还有负载 平衡问题继续)。

好的,我知道每条消息都会自动完成 HTTP 身份验证 - 但是如何?用户名/密码是否随每个请求一起发送?这不只是增加了攻击面吗?我觉得我错过了拼图的一部分。

拥有一个接受 GET 请求的 REST 服务(例如 /session)会很糟糕,您可以在其中传递用户名/密码作为请求的一部分,并在身份验证通过时返回会话令牌成功,然后可以与后续请求一起传递?从 REST 的角度来看,这是否有意义,还是没有抓住重点?

【问题讨论】:

每个请求总是经过身份验证,会话劫持是一回事。 restful 使这一点更加明显,但不会更加暴露。 【参考方案1】:

REST 服务要求对每个 HTTP 请求进行身份验证的情况并不少见。例如,Amazon S3 要求每个请求都具有从用户凭证、要执行的确切请求和当前时间派生的签名。这个签名在客户端很容易计算,可以被服务器快速验证,对拦截它的攻击者使用有限(因为它是基于当前时间的)。

【讨论】:

+1 您能否详细说明:对拦截它的攻击者的用途有限(因为它基于当前时间)?你不是在谈论一个包含加密用户名和密码的cookie吗?像这样吗? (恕我直言) @RoyiNamir:我不是在谈论 cookie。 S3 使用的签名是 HTTP 请求的参数,但不是 cookie,它会为每个请求重新计算。 那么如果我需要保存一些关于用户的信息,我应该把它保存在哪里?在分贝?我不想将每个请求都发送给 db.... 我仍然想使用 rest....你能帮忙吗? @RoyiNamir:如果您对如何完成某个目标有具体问题,请ask a new question。我无法在 cmets 中回答其他问题。 对我来说,这听起来像是摘要访问身份验证en.wikipedia.org/wiki/Digest_access_authentication 的应用。【参考方案2】:

要实现 RESTful,每个 HTTP 请求本身都应该携带足够的信息以供其接收者处理它,以完全符合 HTTP 的无状态特性。

好的,我得到了 HTTP 身份验证 在每条消息上自动完成 - 但是怎么做?

是的,每个请求都会发送用户名和密码。这样做的常用方法是基本访问身份验证摘要访问身份验证。是的,窃听者可以捕获用户的凭据。因此,可以使用传输层安全性 (TLS) 加密所有发送和接收的数据。

拥有 REST 会不会很糟糕 服务,比如说,/session,它接受一个 GET 请求,您将在其中传递一个 用户名/密码作为 请求,并返回一个会话令牌 如果认证成功, 然后可以通过 后续请求?这是否使 从 REST 的角度来看,或者是 没抓住重点?

这不是RESTful,因为它带有状态,但它很常见,因为它为用户提供了便利;用户不必每次都登录。

您在“会话令牌”中描述的内容通常称为登录 cookie。例如,如果您尝试登录 Yahoo!帐户有一个复选框,上面写着“让我登录 2 周”。这本质上是说(用你的话来说)“如果我成功登录,让我的会话令牌保持活动状态 2 周。” Web 浏览器会在您要求它为您发出的每个 HTTP 请求中发送此类登录 cookie(可能还有其他)。

【讨论】:

这个答案对我来说毫无意义。首先,它说每次都可以传递登录名和密码,因此也可以传递一次,这是有道理的。然后,提出了以令牌的形式向客户端返回成功登录状态的想法。如果需要,令牌可以对创建时间进行编码。我们当然可以将信息返回给客户。所以,这个建议对我来说似乎很好。答案说它不好,因为“它携带状态”,但是“REST”中的“ST”的想法不是可以在客户端和服务器之间传输状态吗?【参考方案3】:

如果您想控制客户端会话的生命周期,我认为您的建议是可以的。我认为 RESTful 架构鼓励您开发无状态应用程序。正如@2pence 所写,“每个 HTTP 请求本身都应该携带足够的信息,以便其接收者能够对其进行处理,以完全符合 HTTP 的无状态特性”

但是,情况并非总是如此,有时应用程序需要告知客户端何时登录或注销,并根据此信息维护锁或许可证等资源。有关此类案例的示例,请参阅我的跟进question。

【讨论】:

【参考方案4】:

好的,我得到了 HTTP 身份验证 在每条消息上自动完成 - 但是怎么做?

“授权:”客户端发送的 HTTP 标头。基本(纯文本)或摘要。

拥有 REST 会不会很糟糕 服务,比如说,/session,它接受一个 GET 请求,您将在其中传递一个 用户名/密码作为 请求,并返回一个会话令牌 如果认证成功, 然后可以通过 后续请求?这是否使 从 REST 的角度来看,或者是 没抓住重点?

会话的整个想法是通过在服务器端维护状态来使用无状态协议 (HTTP) 和哑客户端(Web 浏览器)制作有状态应用程序。 REST 原则之一是“每个资源都可以使用用于超媒体链接的通用语法进行唯一寻址”。会话变量是不能通过 URI 访问的东西。真正的 RESTful 应用程序会在客户端维护状态,通过 HTTP 发送所有必要的变量,最好是在 URI 中。

示例:分页搜索。您将有表单中的 URL

http://server/search/urlencoded-search-terms/page_num

它与可收藏的 URL 有很多共同点

【讨论】:

身份验证信息也无法通过 URI 访问 - 每个人都在谈论将身份验证信息作为请求标头的一部分发送。这与在请求中包含会话令牌有什么不同?我不是说在 URI 中使用会话令牌,而是在请求中传递的数据中使用。 身份验证确定您是否有权执行该操作,并且在 RESTful 应用程序中不会影响其结果。 会话令牌还会确定您是否有权执行该操作。你的意思是它不会影响它的结果?如果调用者未获得授权,他们会收到未授权错误。与会话令牌相同。我真的看不出有什么区别? 不,会话令牌是保存在服务器上的状态句柄。那不是RESTful。至于未授权,我不认为这是结果。我宁愿认为这是一个例外(如在 try/catch 中)。 很公平,vartec - 这是有道理的。感谢您的跟进!【参考方案5】:

不,它没有错过重点。 Google 的ClientLogin 正是以这种方式工作的,但值得注意的例外是客户端被指示使用 HTTP 401 响应进入“/session”。但这不会创建会话,它只会为客户端(临时)在不以明文方式传递凭据的情况下对自己进行身份验证,并让服务器在它认为合适的情况下控制这些临时凭据的有效性。

【讨论】:

@unforgiven3 只要返回的令牌仅用于对用户进行身份验证,而不被服务器用于将用户与存储在服务器上的其他状态相关联,那么我看不出违反了 REST 约束。 @unforgiven3 服务器返回的令牌实际上证明了用户就是他们所说的那个人。因此,不是每个请求都包含用户名和密码,而是每个请求都包含令牌,该令牌的构造方式使服务器可以确信其真实性。 @unforgiven3,达雷尔是对的。回显的令牌必须由客户端在每个 HTTP 请求上发送,就像在基本的摘要式身份验证中一样,直到令牌过期。发生这种情况时,客户端可以重复登录,可选地向用户询问凭据或其他任何内容。如果你愿意,我可以详细说明答案。 编辑:(感谢您及时回答老问题!) 没问题,mogsie,讨论这些类型的事情总是很有趣 :-) 我想我知道你们在做什么,不幸的是我对摘要身份验证的了解还不够,无法真正掌握这个(大多数情况下我只是不明白令牌是如何发回每个 HTTP 请求的,但这似乎是一个实现细节)。但是,我现在明白为什么这种方法不违反 REST 原则了。感谢您的回复! @unforgiven3,这可能会有所帮助:令牌是已签名的信息。所以它是自给自足的。服务器可以在不检查先前存储的状态的情况下验证令牌。所以它只是存储在客户端并来回传输的状态。【参考方案6】:

很多人不太清楚 REST 原则,使用会话令牌并不意味着您始终是有状态的,每次请求发送用户名/密码的原因仅用于身份验证,发送令牌也是如此(由登录过程生成)只是为了决定客户端是否有权请求数据,当您使用用户名/密码或会话令牌来决定显示哪些数据时,您只会违反 REST 约定! 相反,您必须仅将它们用于身份验证(显示数据或不显示数据)

在您的情况下,我说是的,这是 RESTy,但请尝试避免在您的 REST API 中使用本机 php 会话并开始生成您自己的哈希令牌,这些令牌会在确定的时间段内到期!

【讨论】:

谢谢。为什么要避免使用原生 php 会话而使用自己的哈希令牌? 我说的不是什么绝妙的理由,只是为了提高安全性和控制力。 这比接受的答案要好。至少,它接受作为 RESTy 的建议,这是有道理的。但是,我不明白为什么传递的信息不能用于进行用户相关授权。一些用户可能有权访问某些数据,而其他用户则不能。这不会使协议非 RESTful。

以上是关于你能帮我理解这个吗? “常见的 REST 错误:会话无关紧要”的主要内容,如果未能解决你的问题,请参考以下文章

你能帮我理解指针和地址吗?

你能帮我理解 ARM Cortex-A9 上的缓存行为吗?

你能帮我解析这个 JSON 吗?

你能帮我解决keras的尺寸问题吗?

谁能帮我翻译一下

如何创建 C# OTA 代码以根据 ALM 中的测试计划中 Excel 中提供的路径创建文件夹。你能帮我解决这个问题吗?