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


159

免责声明:我是REST思想流派的新手,我正在努力将自己的想法包扎起来。

因此,我正在阅读此页面Common REST Mistakes,我发现我对与会话无关的部分完全感到困惑。这就是页面上所说的:

客户端无需“登录”或“启动连接”。HTTP验证在每条消息上自动完成。客户端应用程序是资源而不是服务的使用者。因此,没有什么可登录的!假设您正在通过REST Web服务预订航班。您不会为服务创建新的“会话”连接。而是您要求“行程创建者对象”为您创建一个新的行程。您可以开始填充空白,然后在网络上的其他位置获取一些完全不同的组件来填充其他空白。没有会话,因此在客户端之间迁移会话状态没有问题。也没有“会话亲缘关系”的问题

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

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


每个请求总是经过验证的,会话劫持是一回事。宁静会使情况更明显,但不会更加暴露。
杰森

Answers:


79

为了实现RESTful,每个HTTP请求应自身携带足够的信息,以便其接收者对其进行处理,以使其与HTTP的无状态本质完全协调一致。

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

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

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

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

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


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

33

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


3
+1您能否详细说明:拦截它的攻击者用途有限(因为它基于当前时间)?您是否在谈论包含加密的用户名和密码的Cookie?像这样吗?(IMHO)
罗伊·纳米尔

2
@RoyiNamir:我不是在谈论cookie。S3使用的签名是HTTP请求的参数,但不是 cookie,它将为每个请求重新计算。
Greg Hewgill

因此,如果我需要保存一些有关用户的信息,该将其保存在哪里?在分贝?我不想将每个请求都发送给数据库。
罗伊·纳米尔

@RoyiNamir:如果您对如何实现某个目标有具体疑问,请提出一个新问题。我无法在评论中回答其他问题。
Greg Hewgill

10

许多人不太清楚REST原理,使用会话令牌并不意味着您总是有状态,每个请求发送用户名/密码的原因仅用于身份验证,并且用于发送令牌(通过登录生成)流程)只是为了确定客户端是否有权请求数据,只有在使用用户名/密码或会话令牌来决定要显示什么数据时,您才违反REST的要求!取而代之的是,您只能将它们用于衰弱(显示数据或不显示数据)

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


1
谢谢。为什么应该避免本机php会话,而是使用自己的哈希令牌?
马修

我说的并不是任何明智的理由,只是为了获得更高的安全性和控制力。
EvilThinker

这比公认的答案更好。至少,它接受RESTy的建议,这很有意义。但是,我看不到为什么不能将传递的信息用于执行依赖用户的授权。一些用户可能有权访问某些数据,而其他用户则不能。这不会使协议成为非RESTful。

8

不,它不会错过重点。Google的ClientLogin正是以这种方式工作的,但明显的例外是,指示客户端使用HTTP 401响应转到“ /会话”。但这并不会创建会话,它只会为客户端(临时)认证自己而不通过明文传递凭据的方式,并为服务器控制这些临时凭据的有效性提供一种方式。


11
@ unforgiven3,只要返回的令牌仅用于验证用户身份,并且不被服务器用于将用户与服务器上存储的其他状态相关联,那么我看不到任何违反REST约束的情况。
Darrel Miller 2010年

4
@ unforgiven3服务器返回的令牌实际上是证明用户就是他们所说的身份。因此,除了包含用户名和密码的每个请求外,每个请求还包括令牌,令牌的构建方式使服务器可以确信其真实性。
Darrel Miller

1
@ unforgiven3,Darrel是对的。客户端必须在每个HTTP请求上发送回显的令牌,就像在基本摘要身份验证中一样,直到令牌过期。发生这种情况时,客户端可以重复登录,可以选择要求用户提供凭据或其他方式。如果您愿意,我可以详细说明答案。 编辑:(感谢您跟上老问题的答案!)
mogsie

1
没问题,Mogsie,总是很有趣地讨论这些类型的问题:-)我想我知道你们在做什么,不幸的是我只是对摘要身份验证不够了解而无法真正掌握它(大多数我只是不了解了解令牌是如何发送回每个HTTP请求的,但这似乎是一个实现细节)。但是,我现在知道为什么这种方法没有违反REST原理。感谢您的回复!
罗布

6
@ unforgiven3,这可能会有所帮助:令牌是签名的信息。因此它是独立的。服务器可以在不检查先前存储的状态的情况下验证令牌。因此,这只是存储在客户端上并来回传输的状态。
Iravanchi 2014年

5

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

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

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

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

示例:分页搜索。您会在表单中输入网址

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

它与可添加书签的网址有很多共同点


4
身份验证信息也无法通过URI访问-每个人都在谈论将身份验证信息作为请求标头的一部分发送。与在请求中包含会话令牌有什么不同?我并不是说要在URI中使用会话令牌,而是要在请求中传递的数据中使用会话令牌。
罗布

身份验证确定您是否有权执行该操作,并且在RESTful应用程序中不会影响其结果。
vartec

4
会话令牌还会确定您是否有权执行该操作。您是什么意思,它不会影响结果?如果呼叫者未被授权,则会收到未授权错误。会话令牌也是如此。我真的看不出区别吗?
罗布

3
不,会话令牌是保存在服务器上的状态句柄。那不是RESTful的。至于未授权,我看不出有什么结果。我宁愿认为这是一个例外(例如在try / catch中)。
vartec

足够公平,vartec-这很有意义。感谢您的跟进!
罗布

3

如果您想控制客户端会话的生存时间,我认为您的建议还可以。我认为RESTful架构鼓励您开发无状态应用程序。正如@ 2pence写道:“每个HTTP请求应自身携带足够的信息,以便其接收者对其进行处理以使其与HTTP的无状态本质完全协调一致”

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.