ChatGPT解决这个技术问题 Extra ChatGPT

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

免责声明:我是 REST 学派的新手,我正试图围绕它展开思考。

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

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

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

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

每个请求总是经过身份验证,会话劫持是一回事。 restful 使这一点更加明显,但没有更加暴露。

z
z8000

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

好的,我知道每条消息都会自动完成 HTTP 身份验证 - 但是如何呢?

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

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

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

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


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

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


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

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

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


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

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


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

好的,我知道每条消息都会自动完成 HTTP 身份验证 - 但是如何呢?

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

拥有一个接受 GET 请求的 REST 服务(例如 /session)会很糟糕,您可以在其中将用户名/密码作为请求的一部分传递,并在身份验证成功时返回会话令牌,这可以然后与后续请求一起传递?从 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 - 这是有道理的。感谢您的跟进!
C
Community

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

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