Cookie、Session和Token的区别

1、Cookie、Session和Token的区别

Cookie是浏览器用来保存用户信息的文件,可以保存比如用户是谁,购物车有哪些商品等。

Session是一次会话,会话是指我们访问网站的一个周期

  • 比如用户打开一个浏览器访问某个位的站点。

  • 在这个站点点击多个超链接查看各个网页,然后关闭浏览器,整个过程称之为一个会话。

token是服务器返回的一个临时签名数据, 可以使用这个签名数据表面用户身份.

为什么会有这三个东西呢? 都是一个目的, 服务器需要知道和自己通话的人是谁, 专业一点就是 服务器需要用某种机制来识别具体的用户.

这要从HTTP协议开始说起, HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话, 自然无法识别用户, 所以诞生了Cookie,session和token

2、什么是Cookie?

Cookie 技术产生源于 HTTP 协议在互联网上的急速发展。随着互联网时代的策马奔腾,带宽等限制不存在了,人们需要更复杂的互联网交互活动,就必须同服务器保持活动状态(简称:保活)。于是,在浏览器发展初期,为了适应用户的需求技术上推出了各种保持 Web 浏览状态的手段,其中就包括了 Cookie 技术。Cookie 在计算机中是个存储在浏览器目录中的文本文件,当浏览器运行时,存储在 RAM 中发挥作用 (此种 Cookies 称作 Session Cookies),一旦用户从该网站或服务器退出,Cookie 可存储在用户本地的硬盘上 (此种 Cookies 称作 Persistent Cookies)

Cookie使用限制:Cookie 必须在 HTML 文件的内容输出之前设置;不同的浏览器 (Netscape Navigator、Internet Explorer) 对 Cookie 的处理不一致,使用时一定要考虑;客户端用户如果设置禁止 Cookie,则 Cookie 不能建立。 并且在客户端,一个浏览器能创建的 Cookie 数量最多为 300 个,并且每个不能超过 4KB,每个 Web 站点能设置的 Cookie 总数不能超过 20 个。

执行流程:

A:首先,客户端会发送一个http请求到服务器端;

B: 服务器端接受客户端请求后,发送一个http响应到客户端,这个响应头,其中就包含Set-Cookie头部;意思就是浏览器建立一个cookie保存服务器指定的内容,比如用户信息和用户操作信息;

C:在客户端发起的第二次请求(注意:如果服务器需要我们带上Cookie,我们就需要在B步骤上面拿到这个Cookie然后作为请求头一起发起第二次请求),提供给了服务器端会从收到的cookie中识别用户身份,就能让页面为你提供专门属于你的内容了。

D:服务器端可以用来唯一标识客户端身份的信息。

cookie 可以让服务端跟踪每个客户端的访问,但是每次客户端的访问都必须传回这些 Cookie,如果 Cookie 很多,这无形地增加了客户端与服务端的数据传输量,

为了方便理解,可以先看下这张流程执行图加深概念:

img

cookie具有以下特点

  • cookie存储的数量和字符数量都有限制,只能存储几十个,不超4096左右个字符。
  • Cookie具有不可跨域名性

  很多网站都会使用Cookie。例如,Google会向客户端颁发Cookie,Baidu也会向客户端颁发Cookie。那浏览器访问Google会不会也携带上Baidu颁发的Cookie呢?或者Google能不能修改Baidu颁发的Cookie呢?

  答案是否定的。Cookie具有不可跨域名性。根据Cookie规范,浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。

  Cookie在客户端是由浏览器来管理的。浏览器能够保证Google只会操作Google的Cookie而不会操作Baidu的Cookie,从而保证用户的隐私安全。浏览器判断一个网站是否能操作另一个网站Cookie的依据是域名。Google与Baidu的域名不一样,因此Google不能操作Baidu的Cookie。

需要注意的是,虽然网站images.google.com与网站www.google.com同属于Google,但是域名不一样,二者同样不能互相操作彼此的Cookie。
————————————————
版权声明:本文为CSDN博主「想名真难」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u014600626/article/details/107807029

  • cookie虽然不可跨域名, 但是存储在用户浏览器里也是不安全的,任何人都能直接查看。

img

我们以谷歌浏览器为例查看cookie,我们右击找到检查,点击打开浏览器控制台,或者按F12

img

找到Console,在其中输入document.cookie即可查看

img


3、关于Session

Cookie 虽然很方便,但是使用 Cookie 有一个很大的弊端,

1、Cookie 中的所有数据在客户端就可以被修改,数据非常容易被伪造,那么一些重要的数据就不能存放在 Cookie 中了,

2、而且如果 Cookie 中数据字段太多会影响传输效率。

为了解决前面cookie所提到的这些问题,就产生了 Session,Session 中的数据是保留在服务器端的。

总之:Session是对于服务端来说的,客户端是没有Session一说的。Session是服务器在和客户端建立连接时添加客户端连接标志,最终会在服务器软件(Apache、Tomcat、JBoss)转化为一个临时Cookie发送给给客户端,当客户端第一请求时服务器会检查是否携带了这个Session(临时Cookie),如果没有则会添加Session,如果有就拿出这个Session来做相关操作。

Session 的运作通过一个session_id来进行。session_id通常是存放在客户端的 Cookie 中,比如在 express 中(说的是Nodejs),默认是connect.sid这个字段,当请求到来时,服务端检查 Cookie 中保存的 session_id 并通过这个 session_id 与服务器端的 Session data 关联起来,进行数据的保存和修改。

这意思就是说,当你浏览一个网页时,服务端随机产生一个 1024 比特长的字符串,然后存在你 Cookie 中的connect.sid字段中。当你下次访问时,Cookie 会带有这个字符串,然后浏览器就知道你是上次访问过的某某某,然后从服务器的存储中取出上次记录在你身上的数据。由于字符串是随机产生的,而且位数足够多,所以也不担心有人能够伪造。伪造成功的概率比坐在家里编程时被邻居家的狗突然闯入并咬死的几率还低。

session在计算机网络应用中被称为“会话控制”。不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。在服务端保存Session的方法很多,内存、数据库、文件都有。

  1. 客户端浏览器访问网站的时候,

  2. 服务器会向客户浏览器发送一个每个用户特有的会话编号sessionID,让浏览器写入到cookie里(大多数情况)。服务器同时也把sessionID和对应的用户信息、用户操作记录在服务器上,这些记录就是session。

  3. 客户端浏览器再次访问时,会发送cookie给服务器,cookie中就包含sessionID。

  4. 服务器从cookie里找到sessionID,再根据sessionID找到以前记录的用户信息就可以知道他是谁, 之前操控哪些、访问过哪里。

从流程上看cookie和session看起来就是一套东西啊, 其实是不一样的, cookie是文件, 可以存任意东西, sessionID只不过是存的一种数据, 而session数据保存在服务器, 只不过session常见实现方式是借助cookie, 但是可以不用cookie, 使用URL地址重写来实现session。

使用url重写实现Session跟踪
这是在浏览器不支持Cookie的情况下,servlet引入的一种补充的会话机制。当用户发出下一次请求时,如果请求消息中没有包含Cookie头字 段,Servlet引擎则认为客户端不支持Cookie,他将依据请求url参数中的会话标识号来实施会话跟踪。这种方式要求响应消息中出现的超链接地址 后面附带会话标识号参数,用户也必须通过超链接来提交后续的访问请求。
这种技术成为url重写,tomcat发送给客户端的会话标识号的Cookie名称为JSESSIONID。url重写就是将JSESSIONID关键字 作为参数名和将会话标识号作为参数附加到URL后面。如果浏览器不支持Cookie或者关闭Cookie,就必须对所有可能被客户端访问的请求路径进行 URL重写,如超链接,form表单的action属性和重定向的URL

HttpServletResponse接口定义了两个用于URL重写的方法:
encodeURL方法,用于超链接和form表单的action属性中设置的URL进行重写
encodeRedirectURL 方法 用于对传递给HttpServletResponse.sendRedirect方法的URL进行重写
他们根据请求消息中是否含有Cookie头字段来决定是否进行url重写。把URL作为参数传递给这两个方法,他们就能完成url重写,在url后面添加 jsessionid参数及其值。可以关闭浏览器的Cookie,然后,进行实验,在网页源文件中查看URL后面是否有jsessionid参数及其值。

Session的持久化
客户端访问了某个能开启会话功能的资源, web服务器就会创建一个与该客户端对应的HttpSession对象,每个HttpSession对象都要站用一定的内存空间。如果在某一时间段内访问 站点的用户很多,web服务器内存中就会积累大量的HttpSession对象,消耗大量的服务器内存,即使用户已经离开或者关闭了浏览器,web服务器 仍要保留与之对应的HttpSession对象,在他们超时之前,一直占用web服务器内存资源。
web服务器通常将那些暂时不活动但为超时的HttpSession对象转移到文件系统或数据库中保存,服务器要使用他们时再将他们从文件系统或数据库中装载入内存,这种技术称为Session的持久化。
将 HttpSession对象保存到文件系统或数据库中,需要采用序列化的方式将HttpSession对象中的每个属性对象保存到文件系统或数据库中;将 HttpSession对象从文件系统或数据库中装载如内存时,需要采用反序列化的方式,恢复HttpSession对象中的每个属性对象。所以存储在 HttpSession对象中的每个属性对象必须实现Serializable接口。

Session的持久化的作用:
1.提高服务器内存的利用率,保证那些暂停活动的客户端在会话超时之前继续原来的会话
2,在多台web服务器协同对外提供服务的集群系统中,使用Session的持久化技术,某台服务器可以将其中发生改变的Session对象复制给其他服务器。保证了在某台服务器停止工作后可以由其他服务器来接替它与客户端的会话
3,在一个web应用程序重启时,服务器也会持久化该应用程序中所有HttpSession对象,保证客户端的会话活动仍可以继续。
Tomcat使用Session Manager 类来管理Session的持久化,他提供了两个SessionManager类
org.apache.catalina.session.StandardManager
org.apache.catalina.session.PersistentManager
StandardManager是tomcat默认使用的,在web应用程序关闭时,对内存中的所有HttpSession对象进行持久化,把他们保存到文件系统中。默认的存储文件为
<tomcat 安装目录>/work/Catalina/<主机名>/<应用程序名>/sessions.ser
PersistentManager比StandardManager更为灵活,只要某个设备提供了实现org.apache.catalina.Store接口的驱动类,PersistentManager就可以将HttpSession对象保存到该设备
————————————————
版权声明:本文为CSDN博主「mmllkkjj」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mmllkkjj/article/details/6132139

一个完整的Cookie+Session应用过程如下图所示:

img

Session 可以存放在:

1)内存;

2)Cookie本身;

3)redis 或 memcached 等缓存中;

4)数据库中。

线上来说,缓存的方案比较常见,存数据库的话,查询效率相比前三者都太低,不推荐;


随着Web,应用程序,以及移动端的兴起,session验证的方式逐渐暴露出了问题。尤其是在可扩展性方面。

基于服务器验证方式暴露的一些问题:

  1. Seesion:每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,服务器端内存的开销也会不断增加。
  2. 可扩展性:在服务端使用Seesion存储登录信息,伴随而来的是可扩展性问题, 多个服务器之间如何同步sessionID。
  3. CORS(跨域资源共享):当我们需要让数据跨多台移动设备上使用时,跨域资源的共享会是一个让人头疼的问题。在使用Ajax抓取另一个域的资源,就可以会出现禁止请求的情况。
  4. CSRF(跨站请求伪造):用户在访问银行网站时,他们很容易受到跨站请求伪造的攻击,并且能够被利用其访问其他的网站。

在这些问题中,可扩展性是最突出的:

比如说服务端用两个机器组成了一个集群, 小F通过机器A登录了系统, 那sessionID会保存在机器A上, 假设小F的下一次请求被转发到机器B怎么办? 机器B可没有小F的 sessionID啊。

有时候会采用一点小伎俩: session sticky , 就是让小F的请求一直粘连在机器A上, 但是这也不管用, 要是机器A挂掉了, 还得转到机器B去。

那只好做session 的复制了, 把sessionID在两个机器之间搬来搬去, 快累死了。

在这里插入图片描述

后来有个叫Memcached的支了招: 把session id 集中存储到一个地方, 所有的机器都来访问这个地方的数据, 这样一来,就不用复制了, 但是增加了单点失败的可能性, 要是那个负责session 的机器挂了, 所有人都得重新登录一遍, 估计得被人骂死。

在这里插入图片描述

5、什么是Token?

5.1 Token的起源

于是尝试把这个单点负责session存储的机器也搞出集群,增加可靠性, 但不管如何, 这小小的session 对服务端来说是一个沉重的负担.

因此有必要去寻求一种更有行之有效的方法。于是有人就一直在思考, 服务端为什么要保存这可恶的sessionID呢, 只让每个客户端去保存该多好?

可是如果不保存这些sessionID , 怎么验证客户端发给我的sessionID 的确是服务端生成的呢? 如果不去验证,我们都不知道他们是不是合法登录的用户, 那些不怀好意的家伙们就可以伪造sessionID , 为所欲为了。

嗯,对了,关键点就是验证 !

比如说, 小F已经登录了系统, 服务端给他发一个令牌(token), 然后把小F的 user_id和token在数据库(确切说是Redis+数据库)里做关联, 下一次小F 再次通过Http 请求访问我的时候, 把这个token 通过Http header 带过来不就可以了。

当然, 如果一个人的token 被别人偷走了, 那服务器也没办法, 服务器也会认为小偷就是合法用户, 这其实和一个人的sessionID 被别人偷走是一样的。

这样一来, 服务器就不保存sessionID 了,只是生成token , 然后验证token , 用CPU计算时间获取了我的session 存储空间 !

解除了sessionID这个负担, 可以说是无事一身轻, 我的机器集群现在可以轻松地做水平扩展, 用户访问量增大, 直接加机器就行。 这种无状态的感觉实在是太好了!

在Web领域基于Token的身份验证随处可见。在大多数使用Web API的互联网公司中,token是多用户下处理认证的最佳方式。

那些使用基于Token的身份验证的大佬们, 大部分你见到过的API和Web应用都使用tokens。例如Facebook, Twitter, Google+, GitHub等。

基于Token的身份验证的过程如下:

  1. 用户通过用户名和密码发送请求。
  2. 服务端验证, 返回生成的token 给客户端, 同时给数据库Redis里关联token和用户信息
  3. 客户端储存token,并且其后的每一次请求都添加token, token应该在HTTP的头部发送从而保证了Http请求无状态。
  4. 服务端查询Redis+数据库, 验证token并返回数据。

Token的身份认证逻辑:

对比一:如果两个 token 值相同, 说明用户登录成功过!当前用户处于登录状态!

对比二:如果没有这个 token 值, 则说明没有登录成功;

对比三:如果 token 值不同: 说明原来的登录信息已经失效,让用户重新登录。

在这里插入图片描述

5.3 Tokens的优势

无状态
在客户端存储的Tokens是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。

安全性
请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session操作。

token是有时效的,一段时间之后用户需要重新验证。我们也不一定需要等到token自动失效,token有撤回的操作,通过token revocataion可以使一个特定的token或是一组有相同认证的token无效。

CSRF的防御
1、尽量使用POST,限制GET
GET接口太容易被拿来做CSRF攻击,看上面示例就知道,只要构造一个img标签,而img标签又是不能过滤的数据。接口最好限制为POST使用,GET则无效,降低攻击风险。
当然POST并不是万无一失,攻击者只要构造一个form就可以,但需要在第三方页面做,这样就增加暴露的可能性。
2、将cookie设置为HttpOnly
CRSF攻击很大程度上是利用了浏览器的cookie,为了防止站内的XSS漏洞盗取cookie,需要在cookie中设置“HttpOnly”属性,这样通过程序(如JavaScript脚本、Applet等)就无法读取到cookie信息,避免了攻击者伪造cookie的情况出现。
在Java的Servlet的API中设置cookie为HttpOnly的代码如下:
response.setHeader( “Set-Cookie”, “cookiename=cookievalue;HttpOnly”);
3、增加token
CSRF攻击之所以能够成功,是因为攻击者可以伪造用户的请求,该请求中所有的用户验证信息都存在于cookie中,因此攻击者可以在不知道用户验证信息的情况下直接利用用户的cookie来通过安全验证。由此可知,抵御CSRF攻击的关键在于:在请求中放入攻击者所不能伪造的信息,并且该信总不存在于cookie之中。鉴于此,系统开发人员可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务端进行token校验,如果请求中没有token或者token内容不正确,则认为是CSRF攻击而拒绝该请求。
假设请求通过POST方式提交,则可以在相应的表单中增加一个隐藏域:

token的值通过服务端生成,表单提交后token的值通过POST请求与参数一同带到服务端,每次会话可以使用相同的token,会话过期,则token失效,攻击者因无法获取到token,也就无法伪造请求。
在session中添加token的实现代码:

HttpSession session = request.getSession();
Object token = session.getAttribute("_token");
if(token == null I I "".equals(token)) {
session.setAttribute("_token", UUID.randomUUIDO .toString());
}
4、通过Referer识别
根据HTTP协议,在HTTP头中有一个字段叫Referer,它记录了该HTTP请求的来源地址。在通常情况下,访问一个安全受限的页面的请求都来自于同一个网站。比如某银行的转账是通过用户访问http://www.xxx.com/transfer.do页面完成的,用户必须先登录www.xxx.com,然后通过单击页面上的提交按钮来触发转账事件。当用户提交请求时,该转账请求的Referer值就会是
提交按钮所在页面的URL(本例为www.xxx. com/transfer.do)。如果攻击者要对银行网站实施CSRF攻击,他只能在其他网站构造请求,当用户通过其他网站发送请求到银行时,该请求的Referer的值是其他网站的地址,而不是银行转账页面的地址。因此,要防御CSRF攻击,银行网站只需要对于每一个转账请求验证其Referer值即可,如果是以www.xx.om域名开头的地址,则说明该请求是来自银行网站自己的请求,是合法的;如果Referer是其他网站,就有可能是CSRF攻击,则拒绝该请求。
取得HTTP请求Referer:
String referer = request.getHeader(“Referer”);
————————————————
版权声明:本文为CSDN博主「邓盛余」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_35384853/article/details/100141899

可扩展性
Tokens能够创建与其它程序共享权限的程序。例如,能将一个随便的社交帐号和自己的大号(Fackbook或是Twitter)联系起来。当通过服务登录Twitter(我们将这个过程Buffer)时,我们可以将这些Buffer附到Twitter的数据流上(we are allowing Buffer to post to our Twitter stream)。

使用tokens时,可以提供可选的权限给第三方应用程序。当用户想让另一个应用程序访问它们的数据,我们可以通过建立自己的API,得出特殊权限的tokens。

支持多平台跨服务器
只要用户有一个通过了验证的token,数据和资源就能够在任何平台(Android,ios, h5)任何服务器上被请求到。


最后做个三者的比较:

cookie :

  1. cookie由服务器生成,保存在客户端浏览器。

  2. 容易被劫持,不安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗。

  3. cookie可以被用户禁止

  4. 容量小, 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

session

  1. session是由应用服务器维持的一个服务器端的存储空间, 没有对存储的数据量的限制,可以保存更为复杂的数据类型.

  2. session 默认被存在在服务器的一个文件里, 但是实际中可以放在 文件、数据库、或内存中都可以。

  3. 当用户量增多时,会对服务器造成较大压力。

  4. Session的实现方式大多数情况用Cookie保存的,但是也可以使用URL地址重写。

  5. 较安全,用户验证这种场合一般会用 session, 比如金融银行类的产品,

token

1.无状态、可扩展

2.支持移动设备

3.跨服务器调用

4.安全

cookie,session与token的真正区别你真的了解了吗?https://zhuanlan.zhihu.com/p/344757902

image-20211028085822945

posted @ 2021-10-28 09:37  笨拙的小菜鸟  阅读(6075)  评论(2编辑  收藏  举报