关于JWT 的那些事儿

news/2024/5/18 14:29:32 标签: jwt, session, cookie

JWT 英文名是 Json Web Token,是一种用于通信双方之间传递安全信息的简洁的、URL安全的表述性声明规范,经常用于跨域身份验证。

JWT 以 JSON 对象的形式安全地传递信息。因为存在数字签名,因此所传递的信息是安全的。

为什么需要JWT ?

在了解 JWT 之前我们先来看一下为什么需要 JWT

传统方式的局限性

传统的登录方式:用户端输入用户名密码,服务器端校验通过,根据用户信息生成一个 token,将 token 和 user_id 存到数据库或 session会话 中,并将 token 返回给前端,存入cookie,浏览器每次请求都会带上 cookie,服务端根据cookie中的 token 查询用户(如user_id),验证用户有效性。

传统方式存在以下弊端:

① 如果出现XSS(跨站脚本攻击)漏洞,由于 cookie 可以被 js 读取,XSS 漏洞会导致用户 token 被泄露。解决方案:

  • 设置 httpOnly。这样的话 cookie 将不会被 js 读取,浏览器会自动将它加到请求头信息中,但是带来了新的问题,很容易被XSRF(跨站请求伪造)攻击,因为只要当前浏览器开着,另一个界面可以很容易地跨站请求这个界面的内容,因为cookie会被默认发送出去。
  • 设置 secure。这样 cookie 就只能通过 https 传输,可以过滤掉一些使用 http 协议请求的 XSS 注入。

② 将验证信息存到数据库中,每次验证的时候,都需要去数据库中查询,增加了数据库的查询和存储开销。

③ 如果将 token 存到 session 中,也会增加服务器的存储压力。

④ 无法横向扩展。在服务器集群或者面向服务且跨域的结构中,需要数据库来保存 Session 会话,实现多个服务器之间的会话数据共享。在单点登录中为了解决共享 Session 问题,其中一种方法是持久化 Session 数据,但是缺点也非常明显,就是架构修改很困难,验证逻辑需要重写,并且整体依赖于数据库,如果存储 Session 会话的数据库挂掉那么整个身份认证就无法使用,进而导致系统无法登录。

JWT的优势

① 可以通过 URL POST 参数或者 http header 中发送,数据量小,传输速度快。

② 自包含:负载中包含了用户所需要的所有信息,避免多次查询数据库。原来是先拿着 token 去找 user_id,现在是,JWT 的有效载荷中就包含了 user_id 等信息。这样就不需要服务器端存储 Session 信息。

JWT组成

说白了 JWT 就是一段数据,我理解的是它既代表了一种思想,又提供了具体的解决方案

JWT 是由三段字符串和两个 . 组成,类似于这样:xxxxxx.yyyyyy.zzzzzz,每个字符串代表了不同的功能。

JWT 头 Header

JWT 头描述了 JWT 元数据,是一个 JSON 对象,它的格式如下:

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

其中 “alg” 属性表示签名所使用的算法,JWT 签名默认的算法为 HMAC SHA256 ,

“typ” 属性表示令牌类型,这里就是 JWT。

有效载荷Payload

有效载荷是 JWT 的主体,也是个 JSON 对象。有效载荷包含三个部分:

  • 标准注册声明。它一般包括以下内容:

    iss:jwt的签发者/发行人

    sub:主题

    aud:接收方

    nbf:jwt生效时间

    exp:jwt过期时间

    iat:签发时间

    jti:jwt唯一身份标识,可以避免重放攻击

  • 公共声明。

    可以在公共声明添加任何信息,我们一般会在里面添加用户信息和业务信息,但是不建议添加敏感信息,因为公共声明部分可以在客户端解密。

  • 私有声明。

    私有声明是服务器和客户端共同定义的声明,同样这里不建议添加敏感信息。

下面这个代码段就是定义了一个有效载荷:

json{"exp":"201909181230",
     "role":"admin",
     "isShow":false}

哈希签名 Signature

哈希签名的算法主要是确保数据不会被篡改。它主要是对前面所讲的两个部分进行编码,通过 JWT 头定义的算法(“alg”:“HS256”)生成哈希。

③Signature = HMACSHA256(
		base64UrlEncode(①Header) +
		"." +
		base64UrlEncode(②Payload),
		password
)

最终

JWT = Header.Payload.Signature

JWT 使用过程

① Client 通过账号密码登录,Server 验证通过后,将用户的 id 及其他非敏感信息作为JWT Payload,将其与头部分别进行 base64 编码后签名,生成 JWT,然后将 JWT返 回给 Client。

② Client 将收到的 JWT 保存到 localStorage 或者 sessionStorage 中,跳转到登录页或请求 API,将 JWT 发送给 Server;退出登录时,Client 删除保存的 JWT 信息即可。

③ Server端进行过滤器拦截请求(验证JWT的有效性),若通过,则进行业务逻辑操作并想客户端返回数据,若不通过,则返回错误信息, Client 提示错误,跳转回登录页面。

服务端验证 JWT

服务端验证 JWT 的过程就是签名的过程,如何判判断客户端发送的 JWT 就是我刚才给你的那个?关键就在于存储在服务端的密码

JWT 最终是由 Header、Payload、Signature 三部分组成,其中签名又是由 Header 和 Payload 的编码以及密码组成,当客户端发送 JWT 过来,服务端将 Header 和 Payload 以及存储在服务端的密码(一般是加密过的,而不是明文)重新进行签名,然后将此签名与客户端发送的 JWT 中的签名进行比对,如果相同则认为客户端发送过来的这个 JWT 就是我刚才给你发送的那个,从而验证客户端身份。

这里的关键就在于存储在服务端的密码,因为密码只有服务端有,因此就保证了签名的唯一性。而从客户端发送过来的 JWT 中是无法得到的密码的,因为密码通过哈希被包含在了签名中,而哈希是不可逆的,这就避免了JWT 在传输过程中的密码泄漏问题。

JWT 应用场景

JWT 通常用来设计用户认证和授权系统,还有我们通常说的单点登录等。

JWT注意事项

在使用 JWT 时需要注意以下事项:

JWT 默认不加密,如果要写入敏感信息必须加密,可以用生成的原始令牌再次对内容进行加密;

JWT只适合向 web 端传递一些非敏感信息,因为 base64 编码是可逆的,很容易被破解;

JWT 无法使服务器保存会话状态,当令牌生成后在有效期内无法取消也不能更改;

JWT 包含认证信息,如果泄露了,任何人都可以获得令牌所有的权限;因此 JWT 有效期不能太长,对于重要操作每次请求都必须进行身份验证。

JWT本质只能是能够避免了服务端进行存储token的弊端,服务端通过采用数字签名的方式避免只进行验证而不存储,但是JWT本身的明文传输仍然是不安全,JWT可以在SSL的安全通道下进行传输。JWT最大的作用也是认证。


http://www.niftyadmin.cn/n/1690346.html

相关文章

其他:博客园页面美化

看了其他大佬的博客园页面都那么好看,我也决定美化一下自己的博客园,顺便在这里分享一下我的博客园页面美化的方法。这里我选用的模版是SimpleMemory。 效果图 页面定制CSS代码 1)页面透明 #home {opacity: 0.80;margin: 0px auto;width…

SQLProStudio 创建 MySQL 表

同 Navicat 一样,SQLPro Studio是一款macOS平台的数据库可视化管理工具,但是网上对于的 SQLPro Studio的描述较少,这里简单说一下如何用 SQLProStudio 创建表。 打开SQLPro Studio,点号 选择 MySQL 填写内容: Server …

算法:全排列问题——字典序法

求一个排列的下一个排列我们有暴力的n进位法,当然也就有效率较高的字典序法。 例题 洛谷1088 火星人 题目描述 求排列a[1],a[2],a[3],……,a[n]之后的第m个全排列。 输入格式 共三行。 第一行一个正整数N&#xff…

跨域解决方案之CORS及其相关概念

在讲解 CORS 之前先了解以下几个概念 同源策略 同源策略(Same origin policy)是一种约定,是浏览器限制一个域名与另外一个域名的资源的交互的规则,是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则…

「端到端」和「点到点」的联系及区别

端到端与点到点是针对网络中传输的两端设备间的关系而言的。 端到端 端到端传输指的是在数据传输前,经过各种各样的交换设备,在两端设备间建立一条链路,就像它们是直接相连的一样,链路建立后,发送端就可以发送数据&am…

算法:全排列问题——字典中介法

有时我们希望可以找到一个全排列的下m个全排列,而不仅仅是下一个,就这样出现了字典中介法。 例题 洛谷1088 火星人 题目描述 求排列a[1],a[2],a[3],……,a[n]之后的第m个全排列。 输入格式 共三行。 第…

算法:全排列问题——递增进位法

求一个全排列的下m个全排列,有时我们并不想按字典序找,而是想换一种顺序去找。 例题 原创例题 题目描述 求排列a[1],a[2],a[3],……,a[n]之后按递增进位法的第m个全排列。 输入格式 共三行。 第一行一个…

Redis连接报错 Could not connect to Redis at 127.0.0.1:6379: Connection refused

在安装好 Redis ,需要先开启服务端 修改配置文件 我们需要到安装目录 /usr/local/redis-6.0.5下 找到配置 Redis 的配置文件 找到 通用GENERAL 配置 daemonize yes 表示以守护进程的方式运行,默认是 no,我们需要自己开启为 yes 使用配置开…