令牌认证与Cookie

Joh*_*ohn 117 authentication cookies ember.js

令牌认证和使用cookie的身份验证之间有什么区别?

我正在尝试实施Ember Auth Rails演示,但我不明白使用令牌认证背后的原因,如Ember Auth常见问题解答中描述的"为什么是令牌认证?"

Ond*_*dar 277

Http是无国籍的.为了授权您,您必须"签署"您发送给服务器的每个请求.

令牌认证

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

  • 优点:

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

Cookie身份验证

  • 始终通过授权cookie登录对服务器的请求.
  • 优点:
    • Cookie可以标记为"仅限http",这使得无法在客户端进行阅读.这对于XSS攻击保护更好.
    • 开箱即用 - 您不必在客户端实现任何代码.
  • 缺点:
    • 绑定到单个域.(因此,如果您有一个单页应用程序向多个服务发出请求,您最终可能会像反向代理一样做疯狂的事情.)
    • 易受XSRF攻击.您必须实施额外措施,以防止跨站点请求伪造您的站点.
    • 针对每个请求发送(即使对于不需要身份验证的请求).

总的来说,我会说令牌会给你更好的灵活性,(因为你不受单一领域的束缚).缺点是你必须自己做一些编码.

  • 这个答案比接受的答案更接近规范的答案. (38认同)
  • @EugenKonkov没有.不是必须的.仅在添加标题时.如果您愿意或者您不想要,可以从浏览器发送cookie (6认同)
  • 谢谢@ ondrej-svejdar.这是迄今为止最好的答案!我只想与"相当一些编码"部分争论.几乎任何语言都有很多库可用.因此,除非您真的想了解JWT实现的机制,否则无需从头开始. (3认同)
  • `是针对每个请求发送的吗?每个请求都会发送令牌 (2认同)
  • @Zack - 这很重要。cookie 的问题是它们会自动附加到浏览器的请求中。另一方面,令牌通过 javascript 附加到 XHR 请求。evildomain.com 不可能访问 mysite.com 的本地存储(顺便说一句。我不建议将本地存储作为存储令牌的地方)或 ram(我假设您在这里指的是包含令牌的 javascript 变量),因为该变量在不同的浏览器窗口中被沙箱化。 (2认同)
  • `像反向代理这样的疯狂东西。`总的来说,很好的答案,但我觉得这部分有点误导。在单个 URL 端点下反向代理 API 并不疯狂,有时是必需的(SPA 网站必须一次以支持 IE9 客户端)。为您的 API 设置单独的端点非常适合分散负载,尤其是在 SPA 网站中,或者您的 API 被其他应用程序大量使用的场景中。将反向代理标记为“疯狂的东西”有点过分。 (2认同)

dz9*_*902 40

对于 Google 员工

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

有状态

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

机制

  • Cookie = 浏览器进行特殊处理(访问、存储、过期、安全、自动传输)的特殊标头
  • Custom Headers = eg Authorization,只是没有任何特殊处理的标题,客户端必须管理传输的各个方面
  • 其他。可以使用其他传输机制,例如查询字符串是传输身份验证 ID 一段时间的选择,但由于其不安全性而被放弃

状态比较

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

机制比较

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

总结

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

关联


小智 31

  • 令牌需要存储在某处(本地/会话存储或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/

  • 目前尚不清楚你的积分是用于Cookie还是令牌,它们是哪种方式? (13认同)
  • 我不明白为什么你对代币"拥有更多的控制权"而不是你对cookie的控制权. (4认同)

int*_*xel 28

典型的Web应用程序通常是无状态的,因为它的请求/响应性质.HTTP协议是无状态协议的最佳示例.但是,由于大多数Web应用程序需要状态,为了保持服务器和客户端之间的状态,使用cookie使得服务器可以将每个响应发送回客户端.这意味着从客户端发出的下一个请求将包含此cookie,因此将被服务器识别.这样,服务器可以维护与无状态客户端的会话,主要了解应用程序状态的所有内容,但存储在服务器中.在这种情况下,客户端决不会持有,这不是Ember.js的工作方式.

在Ember.js中,情况有所不同.Ember.js使程序员的工作变得更容易,因为它确实为您提供了状态,在客户端,每时每刻都知道它的状态,而不必向服务器请求状态数据.

但是,在客户端中保持状态有时也会引入在无状态情况下根本不存在的并发问题.然而,Ember.js也为您解决了这个问题,特别是ember-data就是为此而构建的.总之,Ember.js是为有状态客户设计的框架.

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

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

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

我希望我的回答会给你的问题带来更多意义.

  • 我仍然不明白为什么令牌比cookie更好/不同.您正在向api服务器发送一些标识有效会话的内容.假设你在一个域上运行所有东西(即使ember和你的api在不同的服务器上,所有你需要做的就是在cdn后面运行,你可能应该这样做)令牌提供的优点是保证额外的设置工作和对定时攻击的额外敏感性? (74认同)
  • 同意迈克尔约翰斯顿.这个答案一直在解释基于令牌的身份验证是什么,但实际上没有回答这个问题.我能看到的最接近的相关信息是在最后一位_"因为ember.js框架的性质,而且因为它更符合状态网络应用程序范例"_但这根本不是一个答案.我也有同样的问题. (41认同)
  • 不要做广告ember.js专注于问的问题..对不起要粗鲁. (9认同)
  • 我同意这里的两条评论......实际上,我觉得整个"这是蠢货的方式"有点像抄袭 (4认同)
  • 老实说,对于cookie和通过其他方式提交的令牌,有状态是一个红色的鲱鱼.我认为它将用户证据的概念与其他用户个人资料信息混为一谈.我可以使用与HTTP标头或其他通道相同的cookie来提交令牌.我认为差异更多的是回避与cookie的单一来源政策相关的问题,或者从后端的本地客户那里消除实施cookie容器的负担. (2认同)
  • 我认为将饼干与代币进行比较就像比较苹果和梨.Cookie是一种传输机制,当然可以用来传输令牌.另一种传输机制是例如授权头.我认为,更相关的讨论是客户端存储状态与服务器端存储状态. (2认同)
  • 不是专家,而且过于简单化:cookie(~有状态)VS token(~无状态)身份验证有点混乱:两者通常都使用cookie并且都有状态。但是 cookie auth 在服务器上的会话中具有状态(如果您想扩展到许多服务器,则不好),并且或多或少通过 cookie 发送会话 id。令牌认证通过cookie发送令牌,服务器可以检查他是否创建了令牌并且它仍然有效。“状态”信息,例如您在网站上选择的信息,可以保存在客户端。 (2认同)

mar*_*999 8

我相信这里有一些混乱.基于cookie的身份验证与HTML5 Web存储现在可用的重要区别在于,浏览器构建为在从设置它们的域请求资源时发送cookie数据.如果不关闭cookie,你无法阻止它.除非页面中的代码发送,否则浏览器不会从Web存储发送数据.页面只能访问存储的数据,而不能访问其他页面存储的数据.

因此,用户担心谷歌或Facebook可能会使用他们的cookie数据的方式可能会关闭cookie.但是,他们没有理由关闭Web存储(直到广告商想出一种方式来使用它).

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


Afz*_*Afz 5

基于令牌的认证是无状态的,服务器不需要在会话中存储用户信息。这提供了扩展应用程序的能力,而无需担心用户登录的位置。基于 cookie 的 Web 服务器框架具有亲和力,而基于令牌的则不是问题。因此,相同的令牌可用于从我们登录的域以外的域中获取安全资源,从而避免了另一个 uid/pwd 身份验证。

非常好的文章在这里:

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


Bha*_*ant 5

使用令牌时...

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

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

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