从”登录“过程看Jwt和Token,以及区分Cookie和Session概念

文章介绍了HTTP协议的无状态特性以及如何通过session和cookie实现用户身份验证,讨论了session和cookie的优缺点,包括安全性、资源占用和分布式环境下的问题。接着引入了token机制,特别是JWT(JSONWebToken),解释了JWT如何解决跨域身份验证问题,以及JWT的组成和验证流程,同时也提到了JWT的优缺点和适用场景。
摘要由CSDN通过智能技术生成

一、从登录过程中的用户认证说起

HTTP简单来说就是一个通信协议,最大的特点就是每一次通信,都是一个独立连接,通信完成,连接就会断开。

输入用户名,密码之后,点击登录,浏览器会跟服务器建立一个TCP连接,浏览器将数据发送给服务器。服务器根据请求内容,将最终的HTML返回给浏览器,浏览器接收到页面内容,此时,你看到了页面。页面加载完成,通信结束,链接断开。

为什么浏览器跟服务器要断开连接呢?因为如果长时间保持这个连接,会占用大量服务器资源,那么服务器能同时服务的客户端数量就变少了。但连接一旦断开,就会带来新的问题,接下来如果我点击个人中心再次向服务器查询我的个人信息。浏览器要跟服务器建立新的链接,服务器该怎么识别我的合法身份,它如何知道我是谁呢?以及我是否登录过呢?

二、至此,引出session概念,时间到回到第一步

当用户名和密码提交给服务器后,服务器/服务端验证通过,服务器会为这次访问建立/生成一个session(会话),也就是说服务器需要为用户的这次会话,做一个临时性记录,将用户基本信息,存储在服务端。登录状态都保存在这个session中,以便用户下次访问服务器可以识别他的身份,服务器给这个session对象分配/生成一个唯一ID号,当服务器向浏览器端返回数据时,会将这个ID一并返回给客户端。(即session还要有对应cookie中的session ID)

我们还要引出cookie技术,服务器将唯一session返回给客户端,相当于把唯一的身份标记给到了客户端,这是验证身份的重要凭证,浏览器会保存号,浏览器下一次访问服务器时,携带这个数据,这样服务器就能准确的识别你是谁,你有没有登录了,这种技术叫做会话跟踪技术,浏览器保存的每一条记录就叫一个cookie,每一个cookie记录本质上就是一个键值对(不过数据内容基本都进行了加密)。这样将数据保存到客户端,减轻了服务端的压力。解决了HTTP的无状态,方便了用户。

但cookie有安全隐患,(除此之外,使用session还有一些不便,比如session不适合移动端,移动端不依赖于cookie;还有在集群的环境中,通过某个服务进行了session的存储,但下一次请求进来的时候可能经过负载均衡,就将其放到了另外一个服务上,但这个服务并没有上一次的session,就无法再次进行身份识别了,这个session也就失效了。

于是又引入了token机制,所谓token其实是另外一种形式cookie,不过需要自己来维护,它并不属于浏览器的规范,当第一次登录成功后,服务器返回的数据中,会携带一个token字符串返回给前端,前端将这个token保存起来,当下次请求服务器时,需前端手动携带这个token,这样就彻底有效避免了跨域访问的安全隐患。(可以避免CSRF攻击

通过token防伪技术(数字签名)可以防止被人假冒token(一个token会包含三部分用户id,IP地址,登录时间,服务器会使用一个密钥,将这段内容加密,得到一个签名,最终形成了一个完整token字符串)。直接取代了cookie和session。与cookie不同的是,token的保存和携带都需要前端手动完成。

请求完登录接口,后端会返回token,前端保存起来,并且封装你的网络请求,并在所有的请求头里,统一都把这个token带上,然后就可以跳转到登录页了。服务器一般会给token设置有效期,token失效后,接口就会返回一个特定的状态码(一般是401)。

三、所以Cookie和Session的区别说白了就是:

(1)cookie是浏览器提供的一种缓存机制,它可以用于维持客户端与服务端之间的会话。

(2)session指的是维持客户端与服务端会话的一种机制,它可以通过cookie实现,也可以通过别的手段实现。

(3)如果用cookie实现会话,那么会话数据会保存在客户端浏览器中,而session机制提供的会话数据是保存在服务端的。

(4) cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,如果考虑到安全应当使用session。

(5) session会在一定时间内保存在服务器上。当访问增多,会比较占用服务器性能,如果考虑到减轻服务器性能方面,应当使用cookie。

(6) 单个cookie在客户端的限制是3K,一个站点在客户端存放的cookie不能3K。

(7) 一般将登陆信息等重要信息存放为session; 其他信息如果需要保留,可以放在cookie中

看到这里可能会引起疑问:把唯一的 session 标识返回给客户端浏览器,然后保存起来,以后访问时带上,这难道不是cookie 吗?没错,session只是一种会话机制,在许多web应用中,session机制就是通

过cookie 来实现的。也就是说它只是使用了cookie的功能,并不是使用cookie完成会话保存。与cookie在保存客户端保存会话的机制相反,session通过cookie的功能把会话信息保存到了服务端。

四、JWT(Json Web Token)的原理

为什么会有JWT的出现?JSON Web Token Introduction - jwt.io

首先不得不提到一个知识叫做跨域身份验证,JWT的出现就是为了更好的解决这个问题,但是在没有JWT的时候,我们一般怎么做呢?一般使用Cookie和Session,流程大体如下所示:

  1. 用户向服务端发送用户名和密码进行验证

  1. 服务端验证之后,相关数据(如用户角色、登录时间等信息)会保存在当前的Session中

  1. 服务端向用户返回一个唯一的session_id,同时在响应请求中设置cookie,属性名为jessionid

  1. 客户端收到之后会保存jessionid,再次请求的时候,会在header中设置,服务端可以从请求头中获取

  1. 服务端验证获取到的sessionid是否存在,即可验证是否是同一用户

使用Cookie和Session这种模式最大的问题之一就是它不支持横向扩展,也就是不支持分布式架构,如果当前只有一台服务器,那就没什么问题,但是在当下的时代,一台服务器往往是不够的,现在绝大多数都是服务器集群。如果是服务器集群,那么在负载均衡的时候就不能保证每次都发送到同一台服务器上,这样的话也就不能验证用户的身份了,但是这对用户是不友好的,用户是感知不到自己的请求发送到了别的服务器上的。

所以这个时候就提出来了让session落库,当一个请求发过来之后,验证服务从数据库去验证用户身份,这样就能让各个服务器正确的验证用户身份信息,但是这样做,依赖性太强,如果这个session数据库挂了,那么整个认证系统都会崩溃。

JWT的面世

因为Cookie和Session的局限性,所有有人提出只让客户端存储数据,服务端不保存任何会话数据,每个请求都被发送回服务器,JWT就出现了。

JWT是Json Web Token的缩写,它将用户信息加密到Token中,服务器不保存任何的用户信息。服务器通过使用保存的密钥验证Token的正确性,只要正确就通过验证。Jwt由三部分组成,Header:描述Jwt的元数据,定义了生成签名的算法以及Token的类型;Payload(负载)用来存放实际需要传递的数据;Signature(签名)服务器通过payload,header和一个密钥(Secret)使用Header里面指定的签名算法(默认是HMAC SHA256 )生成。是一个开放的标准,用于在各方之间以Json对象安全的传输信息,这些信息通过数字签名进行验证和授权,可使用RSA的公钥私钥对JWT进行签名请求流程:用户使用浏览器(客户端)发送账号和密码;服务器使用私钥创建一个jwt ;服务器返回该jwt给浏览器(用户即获取到了jwt,在jwt的有效期内都不用再重复这三步骤,直接进行下面操作即可),浏览器将该jwt串在请求头中向服务器发送请求,服务器校验该jwt,根据授权规则返回资源给浏览器。

上面可能很难理解,把它日常化一下就是在没有网络的年代,部门A要申请部门B的某个机器使用权,部门A肯定要先老大打报告,写申请,最后老大签字同意,部门A再拿着这个带有老大签字的这个申请报告去找部门B,部门B才能同意部门A使用,这就是JWT的流程。

JWT的数据结构

JWT总共包含了三个部分:Header头部、Payload负载、Signature签名。这三部分共同生成Token,三部分之间用“.”做分割

JWT 头部

JWT的头部是一个描述JWT元数据的JSON对象,如下所示:

{
  "alg": "HS256",
  "typ": "JWT"
}

其中的alg:表示的是签名使用的算法,默认为HMAC SHA256(写为HS256),typ:表示的是令牌的类型,JWT的令牌统一写为JWT。

这样的一个Json数据,还需要使用Base64 URL算法将其转为字符串保存。

JWT 负载

负载部分就是JWT的主体内容,同样的也是一个Json对象,它包含了需要传递的数据,但是不能传递敏感数据,因为这部分数据别人也是可以拿到并且解密的。

JWT指定有七个默认字段供选择:

  1. iss:发行人

  1. exp:到期时间

  1. sub:主题

  1. aud:用户

  1. nbf:在此之前不可用

  1. iat:发布时间

  1. jti:JWT ID 用于标识该 JWT

除了默认字段外,我们还可以自定义字段,如下所示:

同样,这部分数据依然是使用Base 64 URL算法转换为字符串加密。

JWT 签名

签名部分是对上面两部分的数据签名,通过指定的算法(在JWT头部指定的算法)生成哈希来确保数据不会被篡改。

一般流程如下:

  1. 在服务器中保存了一个密码(secret),这个密码仅仅保存在服务器中,不对用户开放。

  1. 使用JWT头部指定的签名算法以及服务器中保存的密码(secret)来生成对应的签名

  1. 在计算出签名之后,JWT头、负载、签名,三部分组成一个字符串,每个部分以“.”进行分割,构成JWT对象

JWT的认证流程
  1. 客户端发送信息给服务端,让其进行验证

  1. 服务端验证成功后,返回给客户端一个JWT

  1. 客户端将JWT保存在Cookie或放入HTTP请求的Header Authorization字段中(推荐放在这)

  1. 此后客户端请求的时候都带着JWT去请求服务端,服务端对JWT再进行验证

JWT的缺陷
  1. JWT最大的缺陷就是服务器不会保存会话状态,所以使用期间不能取消令牌或者更改令牌的权限,一旦JWT签发,在有效期内将会一直有效。

  1. 由于JWT不加密,所以JWT不能用来传递敏感数据

  1. 它有着更大的空间占用

  1. 很难应对过期的数据,由于无法废除掉已经颁布的令牌,在令牌过期之前,只能忍受过期的数据

总结
  • 在Web应用中,不能把JWT当作Session使用,绝大多数情况下,传统的cookie-session机制工作得更好

  • JWT适合一次性的命令认证,颁发一个有效期极短的JWT,即使暴露了危险也很小,由于每次操作都会生成新的JWT,因此也没必要保存JWT,真正实现无状态。

五、总结登录过程的前后端交互过程原理

登录过程中的基本原理是浏览器和服务器之间进行数据交互,以验证用户的身份。以下是使用普通登录方法的登录过程:

  1. 用户在浏览器端输入用户名和密码。

  1. 浏览器将用户输入的用户名和密码打包成一个HTTP请求发送给服务器。

  1. 服务器接收到请求后,对用户名和密码进行校验。

  1. 如果用户名和密码正确,服务器会生成一个Session ID(会话标识),并将该Session ID 存储在服务器端。

  1. 然后服务器将生成的Session ID 通过Set-Cookie的方式将其返回给浏览器端。Set-Cookie是一个HTTP响应头字段,用于设置Cookie。

  1. 浏览器接收到服务器返回的Session ID 后,会将该Session ID 存储在本地的Cookie中。

  1. 当用户发起下一次请求时,浏览器会自动将存储在Cookie中的Session ID 添加到该请求的HTTP头部中。

  1. 服务器通过读取请求中的Session ID 来验证用户的身份。

上述过程中,用户的身份信息不会直接传输给服务器,而是通过Session ID 进行验证。这样做的好处是可以减少敏感信息的传输,并增加登录的安全性。

那如果使用JWT方法来实现登录,则是:

JWT(JSON Web Token)是一种开放的、标准化的身份验证和授权机制。它可以用于在浏览器和服务器之间进行身份验证和授权信息的传递。以下是使用JWT的登录过程中,浏览器和服务器的交互过程:

  1. 用户在浏览器中输入用户名和密码,并通过表单提交给服务器。

  1. 服务器验证用户输入的用户名和密码是否正确。

  1. 如果验证成功,服务器会生成一个包含用户身份信息的JWT,并将其返回给浏览器。

  1. 浏览器接收到JWT后,将其保存在本地,通常使用浏览器的本地存储(localStorage或cookie)。

  1. 在之后的每个请求中,浏览器都会将JWT作为Authorization头部的Bearer令牌发送给服务器。

  1. 服务器在接收到请求时,会验证JWT的有效性和完整性。验证过程包括验证签名、过期时间等。验证成功后,服务器可以信任JWT中所包含的用户身份信息。

  1. 服务器根据JWT中的身份信息,执行相应的操作或返回对应的资源数据给浏览器。

总结起来,JWT登录过程中,服务器生成并颁发JWT给浏览器,浏览器保存JWT并在每次请求中发送给服务器。服务器通过验证JWT来确认用户的身份。这种方式实现了无状态的身份验证和授权,同时也减轻了服务器的负担,提高了系统的可扩展性。

使用JWT和不使用JWT登录,两种方式上有什么区别吗 ?

使用JWT(JSON Web Token)和不使用JWT登录的主要区别在于身份验证的方式和认证结果的处理。

  1. 身份验证方式:

  • 不使用JWT:通常基于会话(session)的方式进行身份验证。服务器生成一个唯一的会话标识(Session ID),将其存储在服务器端,并通过Cookie或URL参数将Session ID 发送给客户端。

  • 使用JWT:通过使用加密的JWT令牌来进行身份验证。服务器在身份验证后将用户信息编码到JWT令牌中,并将该令牌发送给客户端。

  1. 认证结果处理:

  • 不使用JWT:在不使用JWT时,服务器将在后端保留与会话ID对应的用户信息,并在每次请求时验证会话的有效性。这意味着服务器需要维护会话状态并存储用户信息。

  • 使用JWT:使用JWT登录后,服务器不需要存储或管理任何会话状态。服务器可以通过解码JWT令牌获取用户信息,并验证签名以确保令牌是有效且未被篡改过的。

使用JWT的优势包括减轻服务器的状态管理负担、简化跨域认证、提高可扩展性等。然而,使用JWT也有一些潜在的安全问题需要小心处理,如令牌过期处理、令牌泄露和篡改攻击等。

综上所述,使用JWT相对于传统会话机制不仅能简化身份验证过程,还能提高系统的可扩展性和安全性。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值