令牌认证与Cookie


141

令牌身份验证和使用cookie进行身份验证有什么区别?

我正在尝试实施Ember Auth Rails演示,但我不明白使用Ember Auth FAQ中有关“为什么要进行令牌身份验证?”问题中所述的使用令牌身份验证的原因。


4
可以将令牌分配给您的移动应用程序,并将其存储在变量中(由您自己使用)供以后使用,或通过JavaScript在浏览器中保存(由您自己使用)以用于SPA请求中。Cookie通常在浏览器中使用(由浏览器使用)。
蒂诺·麦克拉伦2015年

2
请参阅2016
Michael Freidgeim

Answers:


34

典型的Web应用程序大多是无状态的,因为它具有请求/响应的性质。HTTP协议是无状态协议的最佳示例。但是由于大多数Web应用程序都需要state才能在服务器和客户端之间保持state,因此使用cookie使得服务器可以将每个响应发送回客户端。这意味着来自客户端的下一个请求将包括该cookie,因此将被服务器识别。这样,服务器可以维持与无状态客户端的会话,并且几乎了解有关应用程序状态的所有信息,但是存储在服务器中。在这种情况下,客户端绝对不会持有state,这不是Ember.js的工作方式。

在Ember.js中,情况有所不同。Ember.js使程序员的工作变得更加轻松,因为它确实在客户端中为您保留了状态,而无需每时每刻都知道服务器的状态,而无需向服务器请求状态数据。

但是,在客户端保持状态有时还会引入并发问题,而这些问题在无状态情况下根本不会出现。但是,Ember.js也会为您处理此问题,特别是在考虑到这一点的基础上建立了余烬数据。总之,Ember.js是一个为有状态客户端设计的框架。

Ember.js不能像典型的无状态 Web应用程序那样工作,其中会话状态和相应的Cookie几乎完全由服务器处理。Ember.js 完全在javascript中保存其状态(在客户端的内存中,而不是在其他某些框架中的DOM中),并且不需要服务器来管理会话。这导致Ember.js在许多情况下(例如,当您的应用处于离线模式时)具有更多的用途。

显然出于安全原因,每次进行请求以进行身份验证时,确实需要某种令牌唯一密钥发送到服务器,这样服务器可以查找发送令牌(该令牌最初由服务器发出),并且在将响应发送回客户端之前,验证其是否有效。

我认为,为什么使用Ember Auth FAQ中所述的而不是Cookie的身份验证令牌的主要原因,主要是因为Ember.js框架的性质,并且还因为它更适合有状态的 Web应用程序范例。因此,在构建Ember.js应用程序时,cookie机制不是最佳方法。

希望我的回答对您的问题有更多的意义。


84
我仍然不明白为什么令牌比cookie更好/不同。您正以某种方式将一些内容发送到api服务器,以标识有效的会话。假设您在单个域上运行所有内容(即使ember和api在不同的服务器上,则要完成此操作所要做的所有工作都在CDN后面运行,无论如何您都应该这样做),令牌提供了哪些优势,可以保证额外的设置工作和计时攻击的额外敏感性?
Michael Johnston

46
同意迈克尔·约翰斯顿。该答案不断说明什么是基于令牌的身份验证,但实际上并未回答该问题。我能看到的最接近的相关信息是“由于ember.js框架的本质,也因为它更适合全状态Web应用程序范例”,但这根本不是一个答案。我也有同样的问题。
丹尼尔(Daniel)

5
我同意都在这里的意见。其实,我觉得整个“这是余烬方式”是有点虎头蛇尾的
Grapho

3
老实说,我认为对于Cookie与通过其他方式提交的令牌相比,有状态性是一个红鲱鱼。我认为这将用户证据的概念与其他用户个人资料信息混为一谈。我可以使用与HTTP标头或其他通道相同的cookie来提交令牌。我认为差异更多在于避免与Cookie的单一来源政策相关的问题,或减轻后端本地客户端实现cookie容器的负担。
Michael Lang

15
不要做广告ember.js专注于所问的问题..对不起,无礼。
Vick_Pk '17

336

Http是无状态的。为了授权您,您必须“签名”要发送到服务器的每个单个请求。

令牌认证

  • 到服务器的请求由“令牌”签名-通常意味着设置特定的HTTP标头,但是,可以在HTTP请求的任何部分(POST正文等)中发送它们。

  • 优点:

    • 您只能授权您希望授权的请求。(Cookie-甚至对于每个请求都发送授权cookie。)
    • 对XSRF免疫(XSRF的简短示例-我将通过电子邮件向您发送一个链接,该链接看起来像<img src="http://bank.com?withdraw=1000&to=myself" />,如果您通过Cookie身份验证登录到bank.com,而bank.com没有任何XSRF方式保护措施,我将仅因您的浏览器将触发对该URL的授权GET请求而从您的帐户中提取资金。)请注意,基于Cookie的身份验证可以采取防伪措施-但您必须实施这些措施。
    • Cookies绑定到单个域。bar.com域无法读取在foo.com域上创建的cookie,而您可以将令牌发送到您喜欢的任何域。这对于使用多个需要授权的服务的单页应用程序特别有用-因此,我可以在域myapp.com上拥有一个Web应用程序,该Web应用程序可以向myservice1.com和myservice2.com发出授权的客户端请求。
  • 缺点:
    • 您必须将令牌存储在某个地方;而Cookie是“开箱即用”存储的。想到的位置是localStorage(con:即使关闭浏览器窗口后令牌仍保留),sessionStorage(pro:在关闭浏览器窗口后令牌仍被丢弃,con:在新标签页中打开链接将呈现该标签页匿名)和Cookie(Pro:关闭浏览器窗口后,令牌将被丢弃。如果您使用会话Cookie,则在新标签页中打开链接时将通过身份验证,并且您不受XSRF的影响,因为您忽略了cookie进行身份验证,您只是将其用作令牌存储。缺点:每个单独的请求都会发送出cookie。如果此cookie并非仅标记为https,那么您就容易受到中间攻击。)
    • 对基于令牌的身份验证进行XSS攻击稍微容易一些(例如,如果我能够在您的站点上运行注入的脚本,则可以窃取您的令牌;但是,基于cookie的身份验证也不是灵丹妙药,而将cookie标记为客户端无法读取纯HTTP,客户端仍然可以代表您发出请求,该请求将自动包含授权cookie。)
    • 请求下载文件(仅适用于授权用户)要求您使用File API。对于基于cookie的身份验证,该请求即开即用。

Cookie验证

  • 对服务器的请求始终通过授权cookie登录。
  • 优点:
    • Cookie可以标记为“仅HTTP”,这使得它们无法在客户端读取。这对于XSS攻击保护更好。
    • 开箱即用-您不必在客户端上实现任何代码。
  • 缺点:
    • 绑定到单个域。(因此,如果您有一个向多个服务发出请求的单页应用程序,则最终可能会做出疯狂的事情,例如反向代理。)
    • 易受XSRF攻击。您必须采取额外的措施,以保护您的站点免受跨站点请求伪造的侵害。
    • 对于每个单个请求(甚至对于不需要身份验证的请求)都发送出去。

总体而言,我想说令牌可以为您提供更好的灵活性(因为您没有绑定到单个域)。缺点是您必须自己做一些编码。


56
这个答案比公认的答案更接近规范答案。
xlecoustillier '16

3
谢谢@ ondrej-svejdar。到目前为止,这是最好的答案!我只会与“相当一些编码”部分争论。有大量的库可用于几乎所有语言。因此,除非您真的想了解JWT实现的机制,否则无需从头开始。
FullStackForger

2
Are send out for every single request令牌为每个请求发送过
尤金Konkov

10
@EugenKonkov号 没必要。仅当您添加标题时。如果需要,可以从浏览器发送cookie
Royi Namir

2
@Zack-这很重要。Cookie的问题是浏览器会自动将它们附加到请求中。另一方面,令牌是通过javascript附加到XHR请求的。evildomain.com不可能访问mysite.com的本地存储(顺便说一句。我不建议将本地存储用作存储令牌的地方)或ram(我假设您的意思是此处的Javascript变量包含令牌),因为变量在不同的浏览器窗口中被沙箱化。
Ondrej Svejdar

34
  • 令牌需要存储在某个地方(本地/会话存储或cookie)

  • 令牌可以像cookie一样过期,但是您拥有更多控制权

  • 本地/会话存储无法跨域使用,请使用标记Cookie

  • 预检请求将在每个CORS请求上发送

  • 当您需要流式传输某些内容时,请使用令牌获得已签名的请求

  • 使用XSS比使用XSRF更容易

  • 令牌在每次请求时发送,请注意其大小

  • 如果您存储机密信息,请加密令牌

  • JSON Web令牌可以在OAuth中使用

  • 令牌不是灵丹妙药,请仔细考虑您的授权用例

http://blog.auth0.com/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies/

http://blog.auth0.com/2014/01/07/angularjs-authentication-with-cookies-vs-token/


14
目前尚不清楚您的积分是针对Cookie还是令牌,它们是哪种方式?
Pureferret

6
我不明白为什么您对令牌的控制要比对Cookie的控制更多。
亚伦2015年

@onsmith据我了解,这里不仅仅是一个要点。首先,cookie随每个请求一起发送。发送令牌是由javascript代码触发的。它们不会自动发送。同样,根据rfc部分4,看起来JWT被设计为用于在各方之间传输安全声明的容器。它提供了更精细的控制,并能够为具有权限集的第三方生成身份验证令牌,从而允许他们代表您使用它们。
FullStackForger

18

对于Google员工

  • 不要将状态状态转移机制混合在一起

状态

  • 有状态 =在服务器端保存授权信息,这是传统方式
  • 无状态 =在客户端保存授权信息以及签名以确保完整性

机制

  • Cookie =通过浏览器进行特殊处理(访问,存储,到期,安全,自动传输)的特殊标头
  • 自定义标题 =例如Authorization,只是标题,没有任何特殊处理,客户必须管理转移的所有方面
  • 其他。可以使用其他传输机制,例如查询字符串是传输身份ID的一种选择,但由于其不安全性而被放弃

状态比较

  • “有状态授权”是指服务器在服务器上存储和维护用户授权信息,使授权成为应用程序状态的一部分
  • 这意味着客户端只需要保留一个“身份验证ID”,服务器就可以从其数据库中读取身份验证详细信息
  • 这意味着服务器保留一个活动身份验证池(已登录的用户),并将针对每个请求查询此信息。
  • “无状态授权”表示服务器不存储和维护用户身份验证信息,它只是不知道哪些用户已登录,并依靠客户端生成身份验证信息
  • 客户端将存储完整的身份验证信息,例如您的身份(用户ID),以及可能的权限,到期时间等,这不仅是身份验证ID,还为它提供了新的名称令牌
  • 显然客户端是不可信的,因此auth数据与从生成的签名一起存储hash(data + secret key),其中秘密密钥仅对服务器已知,因此可以验证令牌数据的完整性。
  • 请注意,令牌机制仅能确保完整性,而不能保证机密性,客户端必须实施该机制
  • 这也意味着对于每个请求,客户端必须提交完整的令牌,这会产生额外的带宽

机理比较

  • “ Cookie”只是标题,但在浏览器上已预先加载了一些操作
  • Cookie可以由服务器设置,也可以由客户端自动保存,并且会自动发送到相同的域
  • Cookie可以标记为,httpOnly从而阻止客户端JavaScript访问
  • 预加载的操作可能无法在浏览器以外的平台(例如移动设备)上使用,这可能会导致额外的工作量
  • “自定义标头”只是没有预加载操作的自定义标头
  • 客户端负责接收,存储,保护,提交和更新每个请求的自定义标头部分,这可能有助于防止一些简单的恶意URL嵌入

总结

  • 没有魔术,身份验证状态必须存储在服务器或客户端的某个位置
  • 您可以使用Cookie或其他自定义标头实现有状态/无状态
  • 当人们谈论这些事情时,他们的默认思维方式主要是:无状态=令牌+自定义标头,有状态=身份验证ID + Cookie;这些不是唯一可能的选择
  • 它们各有利弊,但即使是加密令牌,也不应存储敏感信息

链接


1
谢谢您的帮助,对您有很大帮助。回答问题,再加上突然谈论有状态性的其他答案引起的所有困惑。
MDave

非常非常好。带来更多细节,并以更好的方式真正说明其方式和原因。
colinwong

8

我相信这里有些混乱。基于cookie的身份验证与HTML5 Web存储现在可以实现的区别之间的显着区别是,浏览器被构建为在每次向设置它们的域请求资源时发送cookie数据。您必须关闭Cookie才能避免这种情况。除非页面中的代码发送数据,否则浏览器不会从Web存储发送数据。页面只能访问其存储的数据,而不能访问其他页面存储的数据。

因此,用户担心Google或Facebook使用其cookie数据的方式可能会关闭cookie。但是,他们没有太多理由关闭网络存储(直到广告商找到一种使用它的方式)。

因此,这就是基于cookie和基于令牌的区别,后者是使用Web存储的。


5

基于令牌的身份验证是无状态的,服务器无需在会话中存储用户信息。这提供了扩展应用程序的能力,而不必担心用户登录的位置。Web Server Framework与基于Cookie的关联性很高,而基于令牌的问题并不存在。因此,可以使用相同的令牌从我们登录的域之外的域中获取安全资源,从而避免了另一个uid / pwd身份验证。

很好的文章在这里:

http://www.toptal.com/web/cookie-free-authentication-with-json-web-tokens-an-example-in-laravel-and-angularjs


3

在以下情况下使用令牌:

需要联盟。例如,您要使用一个提供程序(令牌分配器)作为令牌发行者,然后将您的api服务器用作令牌验证器。应用可以向令牌分发器进行身份验证,接收令牌,然后将该令牌提供给您的api服务器以进行验证。(同样适用于Google登录,Paypal或Salesforce.com等)

需要异步。例如,您希望客户端发送一个请求,然后将该请求存储在某个地方,以便由单独的系统“稍后”执行。该单独的系统将没有与客户端的同步连接,并且可能没有与中央令牌分配器的直接连接。异步处理系统可以读取JWT,以确定该工作项是否可以并且应该在以后的时间完成。在某种程度上,这与上面的联合会想法有关。不过请注意:JWT到期。如果保存工作项的队列在JWT的生存期内未得到处理,则声明将不再受信任。

需要Cient Signed请求。在此,请求由客户端使用其私钥签名,服务器将使用客户端已注册的公钥进行验证。


1

主要区别之一是cookie受制于同源起源策略,而令牌则不受制。这会产生各种下游效果。

由于cookie仅与特定主机之间来回发送,因此该主机必须承担验证用户身份的负担,并且用户必须在该主机上创建一个具有安全性数据的帐户,才能进行验证。

另一方面,令牌是发行的,不受同一原始政策的约束。发行者实际上可以是任何人,由主机来决定信任哪个发行者。像Google和Facebook这样的发行人通常受到良好信任,因此主机可以将验证用户身份的负担(包括存储所有用户安全数据)转移到另一方,并且用户可以将其个人数据合并到特定发行人下,而不必记住与之交互的每个主机的一堆不同的密码。

这允许单点登录方案,以减少用户体验中的总体摩擦。从理论上讲,随着专门的身份提供者出现以提供身份验证服务,而不是让每个主要网站都旋转自己的,可能是半熟的身份验证系统,网络也变得更加安全。随着这些提供商的出现,为非常基本的资源提供安全的Web资源的成本趋向于零。

因此,总的来说,令牌减少了与提供身份验证相关的摩擦和成本,并将安全Web各个方面的负担转移给了能够更好地实现和维护安全系统的集中方。

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.