前言
故事还要从500年前说起
http
出生了,孩子可爱至极,人见人爱,可是缺少一个重要零部件,那就是,他是无状态的,也就是说他是天生脸盲,分不清爹和隔壁老王。这真是一个头疼的问题呀
也就是说http
不知道当前用户是谁。
但是总不能让用户登录了,跳转一个页面又登录吧。
我们以前是如何处理这种问题的呢?
先看下一般的认证流程,基于 session_id
和 Cookie
实现
- 用户向服务器发送用户名和密码。
- 服务器验证通过后,在当前对话(
session
)里面保存相关数据,比如用户角色、登录时间等等。 - 服务器向用户返回一个
session_id
,写入用户的Cookie
。 - 用户随后的每一次请求,都会通过
Cookie
,将session_id
传回服务器。 - 服务器收到
session_id
,找到前期保存的数据,由此得知用户的身份。
SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。
看起来挺麻烦的哈,而且有很多的局限性,到底是因为哪些局限性从而促进了jwt
的诞生呢?
- 服务端压力增大:每个用户通过认证之后都会将
session
数据保存在服务端,而随着用户增多,服务器压力增大 csrf
攻击:session
是依赖于cookie
的,cookie
如果被截获了,那么就会造成csrf
攻击(jwt不依赖于cookie,jwt在本地存储)- 扩展性不强:如果将来搭建了多个服务器,虽然每个服务器都执行的是同样的业务逻辑,但是session数据是保存在内存中的(不是共享的),用户第一次访问的是服务器1,当用户再次请求时可能访问的是另外一台服务器2,服务器2获取不到session信息,就判定用户没有登陆过。
基于这些局限性,诞生了jwt
jwt是什么?
JWT
(JSON Web Token
)可用于Web
应用程序和API
的身份验证和授权目的,它们被广泛用作无状态身份验证的标准,因为它们消除了服务器端会话的需要。 JWT
易于实施并且与平台无关,因此在Web
开发人员中很受欢迎。
什么是无状态身份验证?
正因为jwt可以进行无状态身份验证,才让他成为了标准,坐稳了帝位。解决了传统验证方式的所有局限性,你掌握了无状态身份验证也就掌握了本节内容接下来我们就围绕无状态身份验证来说一下
无状态身份验证是指服务器在进行用户身份验证时不需要存储任何会话信息或状态信息,完全基于 JWT 进行验证和授权。
传统的身份验证方式通常涉及到会话管理,服务器需要存储用户的会话信息,比如用户登录状态、权限等。这导致服务器需要维护会话状态并存储相关信息,增加了服务器的复杂性和开销。
而使用 JWT 进行无状态身份验证,服务器在用户登录成功后,会生成一个 JWT,将用户的身份信息(如用户ID、角色等)以及其他必要的信息(如过期时间、签名等)封装在 JWT 中,并将 JWT 发送给客户端。客户端在后续的请求中将 JWT 作为身份凭证发送给服务器。
服务器在接收到 JWT 时,通过验证 JWT 的签名,并解析其中的信息,即可确定用户的身份和权限。由于 JWT 中已经包含了用户的身份信息,服务器无需存储会话信息,因此可以轻松地进行水平扩展,提高了系统的可伸缩性和性能。
无状态身份验证的特点有:
- 无需存储会话信息:服务器不需要在内存或数据库中存储任何会话信息,减轻了服务器的负担。
- 节省资源:不需要进行会话状态的检查和管理,减少了服务器的开销。
- 可伸缩性:服务器可以轻松地进行水平扩展,因为每个请求都是独立的,服务器无需维护会话状态。
- 安全性:JWT 使用数字签名验证其完整性和真实性,防止伪造和篡改。
jwt是如何做到无状态的
JWT实现无状态身份验证的关键在于将用户的身份信息和其他必要的信息封装在JWT中,并在每个请求中将JWT作为身份凭证发送给服务器。服务器在接收到JWT后,通过验证JWT的签名和解析其中的信息,即可确定用户的身份和权限。
具体来说,JWT实现无状态身份验证的过程如下:
-
用户登录:用户提供有效的凭证(如用户名和密码),服务器验证凭证的有效性。
-
生成JWT:服务器在用户登录成功后,生成一个JWT。JWT由三部分组成:头部(Header)、负载(Payload)和签名(Signature)。
- 头部:头部指定了JWT的类型(typ)和所使用的签名算法(alg)。
- 负载:负载包含了用户的身份信息(如用户ID、角色等)和其他必要的信息(如过期时间、发布时间等)。
- 签名:签名是对头部和负载进行签名的结果,使用服务器端的密钥进行签名。
负载结构如下
json
{
"姓名": "王二",
"角色": "管理员",
"到期时间": "2023年8月31日0点0分"
}
jwt流程图
-
发送JWT:服务器将生成的JWT发送给客户端,可以通过HTTP的响应头或者放在响应的主体中。
-
客户端存储JWT:客户端接收到JWT后,可以将其存储在本地(如浏览器的localStorage)。
-
请求携带JWT:客户端在后续的请求中,将JWT作为身份凭证添加到请求的头部(通常是Authorization头)中。
-
JWT验证:服务器在接收到请求时,从请求的头部中获取JWT,并验证JWT的签名的有效性。如果签名验证通过,服务器会解析JWT的负载,获取用户的身份信息和其他相关信息。
-
身份验证和授权:服务器根据JWT中的信息确定用户的身份和权限,并进行相应的身份验证和授权操作。
通过将用户的身份信息封装在JWT中,并在每个请求中发送JWT作为身份凭证,服务器可以在无需存储会话信息的情况下进行身份验证和授权。这样就实现了无状态身份验证,减轻了服务器的负担,提高了系统的可伸缩性和性能。
jwt的安全
还有一点需要讲的就是jwt
的安全,因为jwt
里面包含认证信息,如果一旦被盗用,损失会很大
JWT 的安全
JWT
默认是不加密,但也是可以加密的。JWT
不加密的情况下,不能将秘密数据写入JWT
JWT
本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT
的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证- 为了减少盗用,
JWT
不应该使用HTTP
协议明码传输,要使用HTTPS
协议传输
总结🤔
- 今天我们讲了通过
cookie
和session_id
构成的传统登录方式,并讲了这种登录方式的局限性 - 因为传统登录方式的局限性,才诞生了
jwt
,jwt
是一种无状态身份验证。然后我们讲了什么是无状态身份验证,以及jwt
是如何实现无状态身份验证的 - 最后我们讲了一下
jwt
的安全,因为jwt
里面包含认证信息,如果一旦被盗用,损失会很大