WEB开发中用户认证的开发:深入了解cookie、session、token

发展历史
1.很久以前,互联网基本上只是浏览文档。由于它作为服务器进行浏览,因此无需注册某个部分中的人员。这段时间我审阅了哪些文件?每个请求都是一个新的HTTP协议,它是一个请求加上一个响应。特别是,我不想记住是谁刚刚发送了 HTTP 请求。每个请求对我来说都是全新的。这是一个非常激动人心的时刻。
2。但随着交互式Web应用程序的出现,比如网上购物网站、需要登录的网站等,我们立即面临一个问题,那就是要管理会话,我们需要记住谁登录了系统,谁去了系统。将商品放入购物车意味着我必须区分每个人。这是一个很大的挑战,因为HTTP请求是无状态的,所以我想出的解决方案是给每个人发送一个会话id(sessionid)。 ),说白了就是一个随机字符串,每个人接收的方式都不一样。每当有人向我发送 HTTP 请求时,我都会发送此字符串,以便我可以区分谁是谁。
3。这样一来,大家都很高兴,但是服务器却不高兴了。每个人只需要存储自己的session ID,服务器需要存储每个人的session ID!如果接入服务器太多,就会有几千甚至几十万。
这对于服务器来说是一个巨大的开销,严重限制了服务器的可扩展性。比如我用两台机器组成一个集群,小F通过A机器登录系统,那么session ID就会保存在A机器中。上面,如果小F的下一个请求转发到B机器怎么办?机器B没有小F的会话ID。
有时候会用一个小技巧:会话粘性,也就是说小F的请求总是卡在机器A上,但是它做到了不起作用。如果A机器挂了,必须转移到B机器。
然后我们需要复制会话。在两台机器之间移动会话 ID 几乎让人筋疲力尽。
后来,一个叫Memcached的人想出了一个技巧:将会话ID集中存储在一个地方,所有机器都会访问该地方的数据。这样就不需要复制了,但是增加了单点故障的可能性。性啊,如果负责会话的机器挂了,大家就得重新登录,很可能会被骂死。
我也尝试过将这台单机放在集群中以提高可靠性,但无论怎样,这个小会话对我来说都是一个沉重的负担
4。于是有人想,我为什么要保存这个可怕的会话呢?让每个客户保存它怎么样?
但是如果不存储这些Session ID,我如何验证客户端发送给我的Session ID是否确实是我生成的? 如果我们不验证,我们不知道他们是否是合法登录用户。那些不怀好意的人可以欺骗会话 ID 并为所欲为。
嗯,对了,重点是验证!例如,
小F已登录系统,我向他发送包含小F用户ID的令牌。下次小F再次请求通过HTTP访问我时,传递这个token。只需包含 Http 标头即可。
但这和session id没有太大区别。任何人都可以伪造,所以我得想办法阻止别人伪造。
然后在数据上签名。例如,我使用 HMAC-SHA256 算法,添加只有我知道的密钥,在数据上创建签名,然后使用该签名和数据作为令牌。因为密钥如果其他人不知道,就无法伪造令牌。
我不保存此令牌。当小F把这个token发给我的时候,我会用同样的HMAC-SHA256算法和同样的密钥对数据再次计算一个签名,并与token中的签名进行比较,如果相同,我就知道了小F登录了,我可以直接获取小F上的用户ID,如果不相同,那么数据部分肯定被篡改了,我对发送者说:对不起,没有认证。
Token中的数据是明文存储的(虽然我想用Base64编码,但不是加密),仍然可以被别人看到,所以我不能在里面存储密码之类的敏感信息。
当然,如果某人的令牌被别人窃取了,那我也无能为力。我也会认为小偷是合法用户。这其实就和某人的session ID被别人盗用是一样的。
这样我就不会保存会话ID。我只是生成令牌,然后验证令牌。我使用 CPU 计算时间来获取会话存储!
会话 ID 已放宽。你可以说我没什么可担心的。我的机器集群现在可以轻松水平扩展。随着用户访问量的增加,我可以直接添加机器。这种无国籍的感觉真好!
Cookie
Cookie 是一个非常具体的东西。它是指一种可以永久保存在浏览器中的数据。它只是浏览器实现的一个数据存储功能。
Cookie由服务器生成并发送给浏览器。浏览器将cookie以kv形式保存到特定文件夹中的文本文件中。下次请求同一网站时,该 cookie 将被发送到服务器。由于cookie存储在客户端,浏览器添加了一些限制,以确保cookie不会被恶意使用,并且不会占用过多的磁盘空间,因此每个域的cookie数量是有限的。
Session
session实际上就是一个会话。这与您与某人交谈时类似。你怎么知道跟你说话的人是张三而不是李四?对方必须具有某些特征(例如外貌)表明他是张三。
会话类似。服务器需要知道当前谁正在向自己发送请求。为了进行这种区分,服务器为每个客户端分配不同的“身份标识符”。这样每次客户端向服务器发送请求时,都会带上这个“身份ID”,服务器就知道该请求来自谁。至于客户端如何存储这个“身份”,有很多种方式。对于浏览器客户端来说,都默认使用cookie。
服务器使用Session将用户的信息临时存储在服务器上。当用户离开网站时,会话将被销毁。这种存储用户信息的方法比cookie更安全,但是session有一个缺陷:如果web服务器是负载均衡的,那么当下一个操作请求转到另一台服务器时,session就会丢失。
Token
基于令牌的身份验证在网络领域的任何地方都可以看到。在大多数使用Web API的互联网公司中,令牌是处理多个用户身份验证的最佳方式。
以下功能允许您在应用程序中使用基于令牌的身份验证
- 无状态且可扩展
- 支持移动设备
- 跨程序❝调用
使用基于令牌的身份验证
您见过的大多数 API 和 Web 应用程序都使用令牌。比如Facebook、Twitter、Google+、GitHub等。
Token的由来
在介绍基于Token的认证原理和好处之前,不妨先了解一下过去的认证是如何进行的。
基于服务器的身份验证
我们都知道HTTP协议是无状态的。这种无状态性意味着程序必须验证每个请求以识别客户端的身份。
在此之前,程序通过服务器上存储的登录信息来识别该请求。这种方法一般是通过保存Session来实现的。
随着互联网、应用程序和移动终端的出现,这种验证方式逐渐暴露出问题。尤其是在可扩展性方面。
基于服务器身份验证方法揭示的一些问题
- 会话:每次经过身份验证的用户发起请求时,服务器都必须创建一条记录来存储信息。随着越来越多的用户发送请求,内存成本将不断上升。
- 可扩展性:使用 Seesion 在服务器内存中存储登录信息会带来可扩展性问题。
- CORS(跨源资源共享):当我们需要跨多个移动设备提供数据时,跨域共享资源可能会很令人头痛。当使用Ajax从另一个域爬取资源时,请求可能会被禁止。
- CSRF(跨站请求伪造):用户访问银行网站时,容易受到跨站伪造攻击,并可被利用访问其他网站。
这些问题中,可扩军衔是最突出的。因此,我们必须找到更有效的方法。
基于令牌的身份验证原理
基于令牌的身份验证是无状态的,我们不会在服务器或会话上存储用户信息。
这个概念解决了在服务器端存储信息时的许多问题
NoSession 意味着您的程序可以根据需要添加或删除机器,而无需担心用户是否登录。如下:
- 用户通过用户名和密码发送请求。
- 程序确认。
- 程序将签名的令牌返回给客户端。
- 客户端存储令牌并将其用于每个请求。
- 服务器验证令牌并返回数据。
每个请求都需要一个令牌。令牌必须在 HTTP 标头中发送,以确保 HTTP 请求是无状态的。我们还设置 Access-Control-Allow-Origin:* 服务器属性以允许服务器接受来自所有域的请求。
需要注意的是,在ACAO头中设计*时,一定不能包含HTTP认证、客户端SSL证书、cookie等证书。
实现思路:
- 验证用户登录,验证成功后将token返回给客户端。
- 客户端接收到数据后,存储在客户端
- 客户端每次访问API时都会带着Token到服务端。
- 服务器使用过滤器确认。如果验证成功,则返回请求数据。如果验证失败,会返回错误码
一旦我们验证了程序中的信息,获得了token,我们就可以用这个token做很多事情了。
我们甚至可以创建基于权限的令牌并将其传递给第三方应用程序。这些第三方应用程序可以获取我们的数据(显然只能使用我们允许的特定令牌)
令牌的优点
无状态且可扩展
存储在客户端的令牌是无状态且可扩展的。基于这种无状态性和不存储会话信息,负载均衡器可以将用户信息从一个服务传输到其他服务器。
如果我们将经过身份验证的用户信息存储在Session中,则每个请求都需要用户向经过身份验证的服务器发送身份验证信息(称为Sessionaffinity)。当用户数量较多时,可能会造成一定的拥堵。
但是别着急。使用token后,这些问题就很容易解决,因为token本身就包含了用户的验证信息。
安全性
在请求中发送令牌而不是 cookie 可以防止 CSRF(跨站点请求伪造)。虽然cookie用于在客户端存储令牌,但cookie只是一种存储机制,并不用于身份验证。不在会话中存储信息可以让我们执行更少的会话。
Token有时间限制,用户必须在一段时间后重新确认。我们不一定需要等到令牌自动过期。代币有提现操作。通过令牌撤销,可以使特定令牌或具有相同认证的一组令牌失效。
可扩展性
令牌可以创建与其他程序共享权限的程序。例如,您可以将随机社交帐户与您自己的帐户(Fackbook 或 Twitter)连接。当我们通过服务登录 Twitter 时(我们将缓冲这个过程),我们可以将这些缓冲区附加到 Twitter 数据流(我们允许 Buffer 发送到我们的 Twitter 流)。
使用令牌时,您可以向第三方应用程序授予可选权限。当用户希望另一个应用程序访问他们的数据时,我们可以通过构建自己的 API 来获取特殊的权限令牌。
多平台跨域
先说一下CORS(跨域资源共享)。在扩展应用和服务时,必须涉及到不同的设备和应用。
当我们的 API 仅提供数据服务时,我们还可以选择通过 CDN 提供资产服务。这消除了我们为应用程序设置快速标头配置后 CORS 带来的问题。
只要用户拥有经过验证的令牌,就可以在任何域上请求数据和资源。
Access-Control-Allow-Origin: *
当您基于默认值创建令牌时,您可以指定一些选项。我们将在后续文章中更详细地描述它,但默认用法将反映在 JSON Web Tokens 中。
最新的程序和文档适用于 JSON Web 令牌。它支持多种语言。这意味着您将来实际上可以更改您的身份验证机制。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。