Cookies是否应在RESTful API中使用?


77

我对用户如何在Web API上执行授权/身份验证的操作特别感兴趣。

身份验证cookie是否与REST哲学兼容,为什么?




1
@JarrodRoberson我的理解是,在另一个站点上回答不会使该问题重复出现在此处
Tom Squires

5
@JarrodRoberson基于每个站点的常见问题解答,我认为问题属于该站点,而不是堆栈溢出。我对有关RESTful体系结构这方面的设计方法论/理念和取舍感兴趣。堆栈溢出旨在解决实施问题,该站点更多关于设计方法和权衡问题。
布兰登·林顿2012年

1
我在这里同意@BrandonLinton,这个问题对于Stackoverflow来说太广泛了,它是关于体系结构和设计方法的问题。OP需要最佳实践和模式,建议和技巧-而不是特定的答案-因此未指定语言。因此,它属于这里。
dooburt 2012年

Answers:


81

理想的ReSTful服务允许客户端(可能不是浏览器中的客户端)在一个请求中执行任何所需的任务;因为执行此操作所需的完整状态由客户端(而不是服务器)保留。由于客户端可以完全控制状态,因此客户端可以自行创建状态(如果合法),并且仅与API对话即可“完成”。

需要cookie可能会变得很困难。对于除浏览器以外的客户端,与查询参数,简单的请求标头或请求正文相比,管理cookie是一个很大的麻烦。另一方面,在浏览器中,使用Cookie可以使很多事情变得简单。

因此,API可能首先在Authorization标头中查找所需的身份验证数据,因为这可能是非浏览器客户端更喜欢放置的地方,但是为了简化和简化基于浏览器的客户端,它可能还会检查会话cookie用于服务器端登录,但Authorization前提是缺少常规标头。

另一个示例可能是一个复杂的请求,通常需要设置很多参数。非交互式客户端将所有数据塞入一个请求不会有麻烦,但是基于HTML表单的界面可能更喜欢将请求分成多个页面(类似于一组“向导”页面),这样就不会向用户显示带有基于先前选择不适用的选项。所有中间页面都可以将值存储在客户端Cookie中,因此只有用户实际提交请求的最后一页才对服务器有任何影响。该API可以在请求正文中查找所需的属性,如果所需的参数不存在,则可以回过头来查看cookie。

编辑:在RE中对@Konrad的评论如下:

相比之下,令牌更难实现,尤其是因为如果不将令牌存储在某个地方,就无法轻易使令牌无效。

嗯...您正在验证服务器端的cookie,对吗?仅仅因为您告诉浏览器在24小时后丢弃cookie并不意味着会。该Cookie可以由技术含量高的用户保存,并在“过期”后很长时间可以重复使用。

如果您不想在服务器端存储会话数据,则应将其存储在令牌(cookie或其他)中。自包含的身份验证令牌有时称为Macaroon。 这在客户端和服务器之间传递的方式(无论是通过cookie,作为额外的标头还是在请求实体本身中)完全独立于身份验证机制本身。


4
+1,我绝对喜欢使用Authorization标头的实用性,但根据对客户最有效的方式“退回” cookie。
布兰登·林顿2012年

我不同意“对于除了浏览器之外的客户端,管理cookie会带来很大的不便……”。通常,大多数HTTP客户端库都支持cookie,例如,HttpClient在.NET中,您可以毫无问题地使用cookie,而您实际上并不需要考虑它。相比之下,令牌更难实现,尤其是因为如果不将令牌存储在某个地方,就无法轻易使令牌无效。
康拉德(Konrad)'18

1
@Konrad只是因为在某些非浏览器客户中很容易,并不意味着在所有客户中都很容易。如果您只需要支持碰巧使用的特定客户端,那很好,但是我将问题解释为与面向公众的API有关。在curl或中wget,管理cookie非常不便,您确实必须一堆考虑。我通过编辑答案回答了您的另一点。
SingleNegationElimination's

注意仅接受cookie会打开CSRF漏洞。另请参阅security.stackexchange.com/a/166798
Michael Osl,

14

是和否-取决于您的使用方式。

Cookie如果用于维护客户端,客户端,客户端以及客户端的客户端状态,则它们是静态的。

如果将服务器状态存储到cookie中,则基本上只是将负载转移到了客户端上-这并不是很麻烦。

那么有哪些例子呢?

宁静:

  • 身份验证详细信息或“已登录”之类的东西
  • 上次浏览的页面或在应用程序中的位置等

不安:

  • 存储会话信息

宁静来自服务器的无状态。客户端可以维护应用程序状态,并将其发送到服务器以说明它们的位置,以便服务器可以决定从那里去。基本上,会话/状态需要历史数据,并且依赖于过去的请求,可以这么说,理想的情况下不需要宁静的应用程序(如果要拥有登录屏幕,则拥有100%纯净的宁静应用程序是不可行的:)


10
如果在客户端上存储“ isLoggedIn”标志,则可能根本不使用任何身份验证。
tdammers'3

这绝对是有道理的-在客户端存储应用程序状态与REST不一致,但是用于表示自身的客户端信息似乎很好。
布兰登·林顿2012年

1
我想补充一点,将身份验证信息放入Cookie可以消除跨站点请求伪造攻击的可能性。有更好的方法,我建议复制Amazon:docs.aws.amazon.com/AmazonS3/latest/API/…– Dobes
Vandermeer

@tdammers如果“ isLoggedIn”标志在JWT中,该怎么办?然后,只要JWT的发布和验证正确,那应该是安全的。
亚伦·斯佩特纳

@AaronJSpetner:不要将JWT用于会话
tdammers

12

一个可以使用cookie。REST允许它们。

REST要求任何会话信息都必须存储在客户端,但是在进行身份验证时,出于安全原因,某些信息必须保留在服务器端。

从我的一篇博客文章中,我们普遍同意将身份验证数据视为与REST无关。因此,服务器可以将某些会话数据保留在自己的身边。

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.