首页 > 编程语言 >【JavaWeb】一文读懂Cookie、Session&Token 的区别和联系

【JavaWeb】一文读懂Cookie、Session&Token 的区别和联系

时间:2024-10-15 20:18:57浏览次数:10  
标签:浏览器 JavaWeb 用户 Token Session Cookie 服务器

大佬精心打造:JavaWeb进阶学习资料》》点击免费获取

【javaWeb】Cookie & Session & SpringSession 原理分析

简介

Cookie、Session、Token 这三者是不同发展阶段的产物,都是为了解决无状态的 HTTP 协议,提升网站的交互体验。但是他们各有优缺点,三者也没有明显的对立关系,反而常常结伴出现,这也是容易被混淆的原因。

明确问题所在:

客户端与服务器端使用Http协议通讯,但是http无状态协议(短socket链接接,而非长socket),

解决方案:

1,客户端每次都携带信息,发送方给服务器(早期的cookie机制)

2,客户端第一次请求,服务器分配唯一标识,客户端之后每次携带标识(中期的Session机制)

3,客户端登陆成功后,服务器发送唯一令牌Tocken(现在JWT机制)

注意:
cookie与session都在用,在中小型项目可以使用Redis实现session共享等方式来实现,
但是目前业界比较看好JWT这种Tocken鉴权模式。

一、Cookie机制

1.1 概述

HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据。它会在浏览器下次向同一服务器再发起请求时,被携带并发送到服务器上。

通常 Cookie 用于告知服务端两个请求是否来自同一浏览器(不同浏览器同一个请求Cookie是不同的)

Cookie 使基于无状态的HTTP协议记录稳定的状态信息成为了可能。

Cookie 主要用于以下三个方面:

会话状态管理(如用户登录状态、购物车等其它需要记录的信息)
个性化设置(如用户自定义设置、主题等)
浏览器行为跟踪(如跟踪分析用户行为等)

当服务器收到 HTTP 请求时,服务器可以在响应头里面添加一个 Set-Cookie 选项。

Java代码实现: 

    Map<String, String> headers = serverHttpRequest.getHeaders();
        String cookie = headers.get("Cookie");
        System.out.println("cookie="+cookie);
        if(cookie==null){
            //生成sessionId
            String sessionId = UUID.randomUUID().toString();
            String host = headers.get("Host");
            //设置Set-Cookie中的sessionId
            serverHttpResponse.getHeaders().put("Set-Cookie","MYTOMSID="+sessionId+"; Domain="+host+"; Path=/; Secure; HttpOnly");
            //设置SessionId
            serverHttpRequest.setSessionId(sessionId);
            //Set-Cookie: JSESSIONID=4918D6ED22B81B587E7AF7517CE24E25.server1; Path=/cluster
        }

 浏览器收到响应后通常会保存下 Cookie,之后对该服务器每一次请求中都通过 Cookie 请求头部将 Cookie 信息发送给服务器。

另外,Cookie 的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。

浏览器请求和服务器响应:

1.2 存在的问题

Cookie 常用来标记用户或授权会话,被浏览器发出之后可能被劫持,被用于非法行为,可能导致授权用户的会话受到攻击,因此存在安全问题。

还有一种情况就是跨站请求伪造 CSRF,简单来说 比如你在登录银行网站的同时,登录了一个钓鱼网站,在钓鱼网站进行某些操作时可能会获取银行网站相关的Cookie信息,向银行网站发起转账等非法行为。

跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。

跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。

由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了 Web 中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。

不过这种情况有很多解决方法,特别对于银行这类金融性质的站点,用户的任何敏感操作都需要确认,并且敏感信息的 Cookie 只能拥有较短的生命周期。

同时 Cookie 有容量和数量的限制,每次都要发送很多信息带来额外的流量消耗、复杂的行为 Cookie 无法满足要求。

二、Session机制

2.1概述

Session 是服务器为每个用户创建的一个临时会话对象。它包含有关用户会话的信息,例如用户ID、登录状态等。Session通过在服务器上存储用户数据,可以跟踪用户的操作,从而实现用户认证和个性化服务。与Cookie不同,Session不存储在用户的计算机上,而是在服务器上。

Session是服务器为每个客户在服务器端开辟的一块空间。

Session 的实现主要两种方式:Cookie 与 URL 重写,而 Cookie 是首选方式。因为各种现代浏览器都默认开通 Cookie 功能,但是每种浏览器也都有允许 Cookie 失效的设置,因此对于 Session 机制来说还需要一个备胎。

将会话标识号以参数形式附加在超链接的URL地址后面的技术称为 URL 重写

原始 URL:

http://taobao.com/getitem?name=baymax&action=buy

重写后的 URL:

http://taobao.com/getitem?sessionid=1wui87htentg&?name=baymax&action=buy

2.2 存在的问题 

1,每一个用户都需要一个 Session,而服务器要保存所有人的 session id。
如果用户量很大,就要有大量的 session id 存储在服务器中。
这对服务器说是一个巨大的开销,严重的限制了服务器扩展能力。

2,可扩展性:在服务端的内存中使用 Seesion 存储登录信息,伴随而来的是可扩展性问题。
如果服务器集群采用均衡负载的方法,用户访问服务器时,Session 会在服务器之间复制转发;
也可以将 Session 存储在数据库中,服务器每次从服务器取 Session 来验证,这些做法都比较麻烦。

3,CORS(跨域资源共享):基于 Cookie 的 Session 不能跨域,同一用户通过网页、手机访问同一页面,
自身端口是不同的,每次访问的服务器端口也可能不同。需要在后端设置允许跨域,
还需要在前端单独设置允许跨域的 Cookie 传递,非常麻烦。

4,CSRF(跨站请求伪造):如果黑客获取到用户的 Cookie,可以冒充用户访问网站,存在风险。

由于 Session 信息是存储在服务端的,因此如果用户量很大的场景,Session 信息占用的空间就不容忽视。对于大型网站必然是集群化&分布式的服务器配置。如果 Session 信息是存储在本地的,那么由于负载均衡的作用,原来请求机器 A 并且存储了 Session 信息,下一次请求可能到了机器 B,此时机器 B 上并没有 Session 信息。

这种情况下要么在 B 机器重复创建造成浪费,要么引入高可用的 Session 集群方案,引入 Session 代理实现信息共享,要么实现定制化哈希到集群 A。

三、Tocken机制

3.1 概述

Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token作为一种具有时效性的验证身份的手段便应运而生。

Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。

Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌;

当第一次登录后,服务器生成一个Token便将此Token返回给客户端;以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码(带上账户+密码早期的Cookie机制)

Token 避免了 Session 机制带来的海量信息存储问题,也避免了 Cookie 机制的一些安全性问题,在现代移动互联网场景、跨域访问等场景有广泛的用途。
 

3.2 Token的验证原理

基于 Token 的身份验证是无状态的,无需将用户信息存在服务器或 Session 中。这种概念解决了在服务端存储信息时的许多问题。NoSession 意味着程序可以根据需要去增减机器,而不用去担心用户是否登录,基于 Token 的身份验证的过程如下:

用户通过用户名和密码发送请求。
服务器做登录校验,校验成功后就返回 Token 给客户端。
客户端储存 Token,并且用于每次发送请求。
服务器端采用 filter 过滤器校验。
校验成功则返回请求数据,校验失败则返回错误码。

Token实现认证流程

1,前端点击登陆,服务器验证账号密码是否正确
2,正确后,服务器生成令牌(生成令牌的技术有很多,比如UUID等)
3,将该令牌存到数据库或redis中,key是uuid(Token),value是userId
4,把令牌返给客户端,客户端把令牌存在cookie中。
5,以后请求的时候就把Token放在请求头里带上
6,服务端收到请求后,从redis中验证该Token是否存在
7,不存在,则说明用户未登录或登录过期
8,存在获取value内容userId。根据userId查询数据库用户信息。
9,如果数据库中存在userId用户,则说明认证成功,可以访问资源。

3.3 JWT实现Tocken

JWT(Json Web Token)是一种可以跨域的认证方案。

它由三部分构成:

Header 头部信息:记录了使用的加密算法信息;
Payload 净荷信息:记录了用户信息和过期时间等;
Signature 签名信息:根据 header 中的加密算法和 payload 中的用户信息以及密钥key来生成,是服务端验证服务端的重要依据。

​header 和 payload 的信息不做加密,只做一般的 base64 编码。服务端收到 token 后剥离出 header 和 payload 获取算法、用户、过期时间等信息,然后根据自己的加密密钥来生成 sign,并与客户端传来的 sign 进行一致性对比,来确定客户端的身份合法性。

这样就实现了用 CPU 加解密的时间换取存储空间,同时服务端密钥的重要性就显而易见,一旦泄露整个机制就崩塌了,这个时候就需要考虑 HTTPS 了。

Signature 签名信息重要性

使用编码后的header和payload以及我们提供的一个密钥,然后使用header中指定的签名算法进行签名。签名的作用是保证JWT没有被篡改过,如果有人对头部以及负载的内容解码之后进行修改,再进行编码,最后加上之前的签名组合形成新的JWT的话,那么服务器端会判断出新的头部和负载形成的签名和JWT附带上的签名是不一样的。如果要对新的头部和负载进行签名,在不知道服务器加密时用的密钥的话,得出来的签名也是不一样的。

3.4 JWT的Token格式

JWT的三部分均用 Base64 进行编码,并使用 . 进行分隔。

一个典型的 JWT 格式的 token 类似xxxxx.yyyyy.zzzzz。

Base64 是可逆的,所以注意在Payload部分不要携带敏感信息。

3.5 Token 的优势

无状态:在客户端存储的 Tokens 是无状态的,且不存储 Session 信息。基于此,负载均衡器能够将用户信息从一个服务传到其他服务器上。
简洁 : 可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快。
自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库。
安全性:请求中发送 token 而不再是发送 cookie 能够防止 CSRF(跨站请求伪造)。即使在客户端使用 cookie 存储 token,cookie 也仅仅是一个存储机制而不是用于认证。
可扩展性:Tokens 能够创建与其它程序共享权限的程序。使用tokens时,可以提供可选的权限给第三方应用程序。当用户想让另一个应用程序访问它们的数据,服务器可以通过建立自己的API,得出特殊权限的tokens。
多平台跨域:对应用程序和服务进行扩展的时候,需要介入各种各种的设备和应用程序。只要用户有一个通过了验证的 token,数据和资源就能够在任何域上被请求到。

四、Cookie&Session&Tocken比较

4.1 Cookie和Session区别

 

 

cookie 数据存放在浏览器上,服务器能够知道其中的信息。session 数据会在一定时间内保存在服务器上,客户端不知道其中的信息,当访问增多,会比较消耗服务器的性能。
cookie 不是很安全,别人可以分析存放在本地的 cookie 并进行 cookie 欺骗。session 相对安全,建议将登录信息等重要信息存放为 session。其他信息如果需要保留,可以放在cookie中。
单个 cookie 保存的数据不能超过4KB,很多浏览器都限制一个站点最多保存20个 cookie。session 容量更大,可以保存对象。
session 中保存的是对象,cookie 中保存的是字符串。
session 不能区分路径,同一个用户在访问一个网站期间,所有的 session 在任何一个地方都可以访问到。cookie 中如果设置了路径参数,同一个网站中不同路径下的 cookie 互相是访问不到的。

4.2 session与tocken区别

 

token存储在客户端;session存储在服务器端;
token提供认证和授权功能,作为身份认证,token安全性比session好,因为每个请求都有签名还能防止监听以及重放攻击;session就必须靠链路层来保障通讯安全,如果你需要实现有状态的会话,仍然可以增加session来在服务器端保存一些状态
token不一定存储;session存在服务器中,增加服务器压力;
token可以跨域;session不可以跨域,它是与域名绑定的,扩展性不强;
token适用于项目级的前后端分离(前后端代码运行在不同的服务器下);session这种会话存储方式方式只适用于客户端代码和服务端代码运行在同一台服务器上
token是时间换空间;session是空间换时间
token是开发定义的;session是http协议规定的;
token和session都是为了身份验证,token被翻译为令牌;session被翻译为会话
token和session都需要去管理过期时间

4.3 Session、Cookies 和 Token 的对比

属性SessionCookiesToken (JWT)
存储位置服务器端客户端(浏览器)客户端(本地存储、Cookies 或 Header)
安全性
因为数据存在服务器端

容易被拦截和篡改

签名验证防止篡改
存储内容用户会话数据可自定义,常存储少量状态信息用户身份信息及其他元数据
状态性有状态,需要服务器端存储会话数据无状态,但可用于维护用户状态无状态,服务器不存储任何会话数据
适用场景多用户、敏感操作管理,适合状态丰富的系统适合存储简单、非敏感数据适合无状态的分布式系统或微服务架构
性能影响服务器存储会话,扩展性差存储在客户端,影响有限无状态,服务器不保存,扩展性强
生命周期管理由服务器控制,会话结束或超时失效由浏览器和服务器设置,过期后自动失效由签发时设置的有效期控制,通常由客户端管理

4.4  Session 和 Token 的使用场景对比

使用场景SessionToken (JWT)
小型系统适合,因为状态较少,服务器可以轻松管理用户会话不适合,增加了不必要的复杂性
大型系统扩展性差,服务器需要管理大量用户的会话状态更适合,Token 是无状态的,服务器压力小,扩展性好
分布式系统不适合,难以在多个服务器之间共享会话状态最适合,Token 可在多个服务之间传递,不需要共享状态
安全性要求可以通过 Session 管理会话和权限,较为安全更安全,Token 自带签名,防止篡改和伪造
微服务架构复杂,因为每个服务需要共享用户的 Session 状态适合,Token 可携带用户身份信息,无需集中存储

五、案例应用

在实际开发中,这些技术通常会结合使用,以实现更安全、高效的身份验证和数据管理。通过充分了解 Cookie、Session 和 Token 的区别,我们可以根据项目需求选择合适的技术,确保用户身份安全和数据传输效率。

假设我们正在开发一个博客平台,用户可以注册、登录并发表文章。

在这个案例中,我们需要解决以下几个问题:

  1. 如何让用户在多个请求之间保持一致的身份?
  2. 如何确保用户数据的安全传输?
  3. 如何避免跨域问题?

针对这些问题,我们可以分别采用 Cookie、Session 和 Token 技术进行解决。

以下是具体实施方案:

1,使用 Cookie 保存用户偏好:

当用户登录博客平台时,服务器会生成一个唯一的 Session ID,并将其存储在 Cookie 中。后续的请求中,客户端携带 Session ID,服务器通过 Session ID 查找对应的 Session 信息来验证用户身份。此外,我们还可以利用 Cookie 保存用户的偏好设置,如主题、语言等。

2,使用 Session 进行数据会话:

在用户登录后,服务器会为该用户创建一个 Session,其中包含用户的用户名、权限等信息。Session 用于保存用户在一段时间内的操作数据,如编辑文章、发表评论等。

通过这种方式,我们可以确保用户数据的安全传输。

3,使用 Token 进行身份验证和跨域认证:

服务器生成一个 Token 并返回给客户端。在后续的请求中,客户端需要将 Token 带上,服务器通过验证 Token 来确定该请求是否合法。这样,我们就可以解决跨域问题,同时确保只有持有有效 Token 的用户才能访问平台。通过以上方案,我们成功解决了博客平台中的身份验证和数据传输问题。

在这个案例中,Cookie、Session 和 Token 各自发挥了重要作用,确保了用户身份的一致性、数据安全性以及跨域问题的解决,然而,它们之间仍存在区别:

  • Cookie 主要应用于客户端存储和个性化设置,如用户偏好、登录状态等。

  • Session 则侧重于服务器端保存用户状态和权限控制,可在多个请求之间保持用户身份一致。

  • Token 则用于身份验证和授权,可解决跨域问题,并确保请求的合法性。

总结:

Cookie 存储用户信息不安全,且受跨域等信息的影响。不过cookie容量小,现在被h5的缓存替代了,就是localStorage和sessionStorage,cookie一般用不到了。

Session存储用的信息,Cookie存储SessionId信息,用户信息通过Map形式存放在服务器,在负载均衡等方式存在问题,不过也有解决方案,Session共享。

用户只要下次请求带上唯一标识SessionId即可,具体是Cookie携带,http请求头部、还是参数携带或者其他方式,需要带上才能有效。服务器才能根据唯一标识找到。

六、扩展:

扩展1:啥是CSRF呢?

攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过(cookie 里带来 sessionId 等身份认证的信息),所以被访问的网站会认为是真正的用户操作而去运行。

那么如果正常的用户误点了上面这张图片,由于相同域名的请求会自动带上 cookie,而 cookie 里带有正常登录用户的 sessionid,类似上面这样的转账操作在 server 就会成功,会造成极大的安全风险

CSRF 攻击的根本原因在于对于同样域名的每个请求来说,它的 cookie 都会被自动带上,这个是浏览器的机制决定的!

至于完成一次CSRF攻击必要的两个步骤:

1、首先登了一个正常的网站A,并且在本地生成了cookie

2、在cookie有效时间内,访问了危险网站B(就获取了身份信息)

Q:那我不访问危险网站就完了呗?

A:危险网站也许只是个存在漏洞的可信任网站!

Q:那我访问完正常网站,关了浏览器就好了呀?

A:即使关闭浏览器,cookie也不保证一定立即失效,而且关闭浏览器并不能结束会话,session的生命周期跟这些都没关系。

拓展2:同源策略?

就是不同源的客户端脚本在没有明确授权情况下,不准读写对方的资源!

同源就是:协议、域名与端口号都相同。

同源策略是由 Netscape 提出的著名安全策略,是浏览器最核心、基本的安全功能,它限制了一个源中加载脚本与来自其他源中资源的交互方式。

拓展3:什么是跨域,如何解决?

当浏览器执行脚本时会检查是否同源,只有同源的脚本才会执行,如果不同源即为跨域。

产生原因:它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。

解决方案:

nginx(静态服务器)反向代理解决跨域(前端常用),a明确访问c代理服务器,但是不知道c的内容从哪里来,c反向从别的地方拿来数据。(忽略的是目标地址),浏览器可以访问a,而服务器之间不存在跨域问题,浏览器先访问a的服务器c,让c服务器作为代理去访问b服务器,拿到之后再返回数据给a。

jsonp:通常为了减轻web服务器的负载,我们把js、css、图片等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许。

拓展4:易于扩展?

比如有多台服务器,使用负载均衡,第一次登录转发到了A,A中seesion缓存了用户的登录信息,第二次登录转发到了B,这时候就丢失了登录状态,当然这样也是有解决方案可以共享session,但token只需要所有的服务器使用相同的解密手段即可。

拓展5:什么是单点登录?

所谓单点登录,是指在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

标签:浏览器,JavaWeb,用户,Token,Session,Cookie,服务器
From: https://blog.csdn.net/zhyooo123/article/details/142914511

相关文章

  • 【JavaWeb】Spring Boot中@Import多种使用方式
    @Import是一个非常有用的注解,它的长处在于你可以通过配置来控制是否注入该Bean,也可以通过条件来控制注入哪些Bean到Spring容器中。比如我们熟悉的:@EnableAsync 、@EnableCaching、@EnableScheduling等等统一采用的都是借助@Import注解来实现的。  需要注意的是:ImportSele......
  • Kubernets 生成永不过期的token
    [root@k8s-master-01~]#kubeadmtokencreate--ttl0m3g8ci.usn0m7xw6xp266xe[root@k8s-master-01~]#kubeadmtokencreate--ttl0c5g3ke.7tcrrnkq6nrov9gk[root@k8s-master-01~]#kubeadmtokenlistTOKENTTLEXPIRESUSAGES......
  • JavaWeb开发
    JavaWeb开发1、程序架构1.1软件类型按照软件性质划分系统软件,应用软件应用软件按照架构来分:C/S架构(Client/Server模式,特征:需要下载客户端【安装包来进行安装到设备上】)B/S架构(Broswer/Server模式)特征:基于浏览器来运行的各种软件,通过http【超文本传输协议】来进行网......
  • 基于javaweb(springboot)城市地名地址信息管理系统设计和实现
    基于javaweb(springboot)城市地名地址信息管理系统设计和实现......
  • 【Spring】获取Cookie和Session(@CookieValue()和@SessionAttribute())
    获取Cookie传统获取Cookie这是没有Spring的时候,用Servlet来获取(获取所有的Cookie)SpringMVC是基于ServletAPI构建的原始Web框架,也是在Servlet的基础上实现的@RequestMapping("/getcookie")publicStringgetCookie(HttpServletRequestrequest, ......
  • Javaweb之SpringBootWeb案例之 登录功能的详细解析
     1.登录功能1.1需求编辑在登录界面中,我们可以输入用户的用户名以及密码,然后点击"登录"按钮就要请求服务器,服务端判断用户输入的用户名或者密码是否正确。如果正确,则返回成功结果,前端跳转至系统首页面。1.2接口文档我们参照接口文档来开发登录功能基本信息请求路径:/login请......
  • javaweb实现下载功能报错sockettimeout
    javaweb压缩zip包下载,并响应头里面指定文件大小在JavaWeb应用程序中,如果你想要创建一个ZIP文件并通过HTTP响应提供下载,并且希望在响应头中指定文件大小,你可以先将文件写入到一个临时的ByteArrayOutputStream中,这样你就可以计算出压缩后的文件大小。然后,你可以将这个字节......
  • 基于redis实现验证码、Token的存储
    多台tomcat服务器之间session信息不能共享(早期tomcat为解决这个问题可以在tomcat服务器之间拷贝session信息但拷贝时有时间延迟故淘汰)1.使用redis替代session1.使用String数据类型存储验证码 每一个手机号作为key2.使用Hash数据结构存储用户信息  随机token作为k......
  • cookie 和 session
    1、cookie通过在客户端记录的信息确定用户身份。http是一种无连接协议,客户端和服务端交互仅限于请求/响应过程,结束后断开,下一次请求时,服务端会认为是一个新的客户端。为了维护连接,让服务端知道这是前一个用户发起的请求,必须在一个地方保存客户端信息。2、sessionsession,中文......
  • 【附源码】个人博客系统(源码+数据库+毕业论文齐全)java开发springboot框架vue javawe
    ......