【JWT】JWT实战应用

发布时间:2024年01月01日

学习参考:BV1gk4y177DS

-------------------------------------------------------------------------------------------------------

# 一、前置知识点

- Java Web

- Spring/SpringMVC/SpringBoot

- Spring Security

# 二、JWT介绍

## 2.1 概念

官网:https://jwt.io/

JSON Web Token,简称 JWT,读音是 [d??t],是一个基于 RFC 7519 的开放数据标准,它定义了一种宽松且紧凑的数据组合方式。其作用是:**JWT是一种加密后数据载体,可在各应用之间进行数据传输**。

JWT中一般涵盖了用户身份信息,每次访问时,server校验信息合法性即可。

## 2.2 JWT组成

一个 JWT 通常由 HEADER (头),PAYLOAD (有效载荷)和 SIGNATURE (签名)三个部分组成,三者之间使用“.”链接,格式如下:

header.payload.signature

**一个简单的JWT案例:**

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9   //header
.eyJ1c2VyX2luZm8iOlt7ImlkIjoiMSJ9LHsibmFtZSI6ImRhZmVpIn0seyJhZ2UiOiIxOCJ9XSwiaWF0IjoxNjgxNTcxMjU3LCJleHAiOjE2ODI3ODM5OTksImF1ZCI6InhpYW9mZWkiLCJpc3MiOiJkYWZlaSIsInN1YiI6ImFsbHVzZXIifQ  //payload
.v1TxJ0mngnVx4t9O3uibAHPSLUyMM7sUM06w8ODYjuE //signature

> 注意三者之间有一个点号(“.”)相连

### 2.2.1 Header组成

JWT的头部承载两部分信息:

- 声明类型,默认是JWT

- 声明加密的算法 常用的算法:HMAC 、RSA、ECDSA等

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

**alg**:表示签名的算法,默认是 HMAC SHA256(写成 HS256);

**typ**: 表示令牌(token)的类型,JWT 令牌统一写为 JWT。

使用Base64加密,构成了JWT第一部分-header:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

### 2.2.2 Payload组成

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的有效信息。

标准载荷:有很多,建议使用,但不强制,对JWT信息作补充。

| 标准载荷              | 介绍                                   |

| --------------------- | -------------------------------------- |

| iss (issuer)          | 签发人(谁签发的)                     |

| exp (expiration time) | 过期时间,必须要大于签发时间           |

| sub (subject)         | 主题(用来做什么)                     |

| aud (audience)        | 受众(给谁用的)比如:http://www.xxx.com |

| nbf (Not Before)      | 生效时间                               |

| iat (Issued At)       | 签发时间                               |

| jti (JWT ID)          | 编号,JWT 的唯一身份标识               |

自定义载荷:可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息。但不建议添加敏感信息,因为该部分在客户端可解密。

{
    "user_info": [
      {
        "id": "1"
      },
      {
        "name": "dafei"
      },
      {
        "age": "18"
      }
    ],
    "iat": 1681571257,
    "exp": 1682783999,
    "aud": "xiaofei",
    "iss": "dafei",
    "sub": "alluser"
}

使用Base64加密,构成了JWT第二部分-payload:

eyJ1c2VyX2luZm8iOlt7ImlkIjoiMSJ9LHsibmFtZSI6ImRhZmVpIn0seyJhZ2UiOiIxOCJ9XSwiaWF0IjoxNjgxNTcxMjU3LCJleHAiOjE2ODI3ODM5OTksImF1ZCI6InhpYW9mZWkiLCJpc3MiOiJkYWZlaSIsInN1YiI6ImFsbHVzZXIifQ

### 2.2.3 signature组成

Signature 部分是对前两部分的签名,防止数据篡改。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

signature = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。

**因为有这个密钥的存在,所以即便调用方偷偷的修改了前两部分的内容,在验证环节就会出现签名不一致的情况,所以保证了安全性。**

使用Base64加密,构成了JWT第三部分-signature:

l6JdYARw4IHmjliSbh9NP6ji1L15qVneWTJU5noQ-k8

## 2.3 在线生成/解析JWT

### 2.3.1 编码工具

地址:https://tooltt.com/jwt-encode/

### 2.3.2 解码工具

地址:https://tool.box3.cn/jwt.html

# 三、JWT特点

### 3.1 无状态

JWT 不需要在服务端存储任何状态,客户端可以携带 JWT 来访问服务端,在服务端直接进行校验(客户端无需缓存JWT),从而使服务端变得无状态。这样,服务端就可以更轻松地实现扩展和负载均衡。

### 3.2 可自定义

JWT 的载荷部分可以自定义,可以存储任何 JSON 格式的数据。这意味着我们可以使用 JWT 来实现一些自定义的功能,例如存储用户喜好、配置信息等等。

### 3.3 扩展性强

JWT 有一套标准规范,因此很容易在不同平台和语言之间共享和解析。此外,开发人员可以根据需要自定义声明(claims)来实现更加灵活的功能。

### 3.4 调试性好

由于 JWT 的内容是以 Base64 编码后的字符串形式存在的,因此非常容易进行调试和分析。

### 3.5 安全性取决于密钥管理

JWT 的安全性取决于密钥的管理。如果密钥被泄露或者被不当管理,那么 JWT 将会受到攻击。因此,在使用 JWT 时,一定要注意密钥的管理,包括生成、存储、更新、分发等等。

### 3.6 无法撤销

由于 JWT 是无状态的,一旦 JWT 被签发,就无法撤销。如果用户在使用 JWT 认证期间被注销或禁用,那么服务端就无法阻止该用户继续使用之前签发的 JWT。因此,开发人员需要设计额外的机制来撤销 JWT,例如使用黑名单或者设置短期有效期等等。

### 3.7 需要缓存到客户端

由于 JWT 包含了用户信息和授权信息,一般需要客户端缓存,这意味着 JWT 有被窃取的风险。

### 3.8 载荷大小有限制

由于 JWT 需要传输到客户端,因此载荷大小也有限制。一般不建议载荷超过 1KB,会影响性能。

# 四、JWT优缺点

## 4.1 优点

- 无状态:JWT 本身不需要存储在服务器上,因此可以实现无状态的身份验证和授权。

- 可扩展性:JWT 的载荷可以自定义,因此可以根据需求添加任意信息。

- 可靠性:JWT 使用数字签名来保证安全性,因此具有可靠性。

- 跨平台性:JWT 支持多种编程语言和操作系统,因此具有跨平台性。

- 高效性:由于 JWT 不需要查询数据库,因此具有高效性。

## 4.2 缺点

- 安全性取决于密钥管理:JWT 的安全性取决于密钥的管理,如果密钥被泄露或者被不当管理,那么 JWT 将会受到攻击。

- 无法撤销令牌:由于 JWT 是无状态的,一旦 JWT 被签发,就无法撤销。

- 需要传输到客户端:由于 JWT 包含了用户信息和授权信息,因此 JWT 需要传输到客户端,这意味着 JWT 有被攻击者窃取的风险。

- 载荷大小有限制:由于 JWT 需要传输到客户端,因此载荷大小也有限制。

# 五、JWT应用场景

## 5.1 一次性验证

用户注册成功后发一份激活邮件或者其他业务需要邮箱激活操作,都是可以使用jwt。

原因:

JWT时效性:让该链接具有时效性(比如约定2小时内激活),

JWT不可篡改性:防止篡改以激活其他账户

## 5.2 RESTful API 的无状态认证

使用 JWT 来做 RESTful api 的身份凭证:当用户身份校验成功,客户端每次接口访问都带上JWT,服务端校验JWT合法性(是否篡改/是否过期等)

## 5.3 信息交换

 JWT是在各方(项目间/服务间)之间安全传输信息的好方式。 因为JWT可以签名:例如使用公钥/私钥对,所以可以确定发件人是他们自称的人。 此外,由于使用标头和有效载荷计算签名,因此您还可以验证内容是否未被篡改。

## 5.4 JWT令牌登录

JWT 令牌登录也是一种应用场景,但也是JWT被诟病最多的地方,因为JWT令牌存在各种不安全。

1>JWT令牌存储与客户端,容易泄露并被伪造身份搞破坏。

2>JWT 被签发,就无法撤销,当破坏在进行时,后端无法马上禁止。

上面问题可通过监控异常JWT访问,设置黑名单 + 强制下线等方式尽量避免损失。

# 六、JWT实战案例

## 6.1 案例1:邮件激活

### 6.1.1 需求与分析<

文章来源:https://blog.csdn.net/weixin_52553215/article/details/135242467
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。