文章目录
前言
本文详细介绍了在Java Spring Boot中实现JWT(JSON Web Token)的完整流程。通过依赖io.jsonwebtoken的jjwt库,我们可以方便地生成、解析和验证JWT。文章提供了配置文件、工具类和初始化配置的详细代码,涵盖了JWT的生成、过期时间设置、刷新机制以及从token中提取信息等功能。这些方法在用户认证、授权和单点登录等场景中具有重要应用,有助于提高Web应用的安全性和效率。
一、JWT的理论知识
1. 什么是 JWT(JSON Web Token)?
JWT(JSON Web Token)是一种基于 JSON 的开放标准 (RFC 7519) ,用于在各方之间作为紧凑且安全的方式传输信息。它常用于认证和授权场景,尤其是在 Web 开发中非常流行。
2. JWT 的组成
一个 JWT 通常由三部分组成,每部分通过 .
分隔:
-
Header(头部):
- 描述令牌的元信息,比如使用的签名算法。
- 通常是一个简单的 JSON 对象,如:
{ "alg": "HS256", "typ": "JWT" }
alg
指定签名算法(如 HS256、RS256),typ
表示令牌的类型(一般为 “JWT”)。
-
Payload(有效载荷):
- 包含实际要传递的数据,例如用户信息或声明(claims)。
- 这是一个 JSON 对象,可以包括:
- 标准声明(预定义字段,如用户 ID、过期时间等)。
- 自定义声明(开发者自定义的数据)。
- 示例:
{ "sub": "1234567890", "name": "John Doe", "admin": true, "exp": 1672444800 }
- 注意:Payload 是可以被 解码和阅读 的,因此不要存储敏感信息。
-
Signature(签名):
- 用于验证 JWT 的完整性,确保它未被篡改。
- 签名是通过以下方式生成的:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
- 如果签名验证失败,JWT 就会被判定为无效。
3. JWT 的特点
-
紧凑性:
- JWT 使用 Base64Url 编码,令牌是一个字符串,适合通过 URL 或 HTTP 请求头传输。
-
自包含性:
- JWT 内部可以包含必要的用户信息,减少了对服务器多次查询的需求。
-
无状态:
- JWT 是一种无状态认证方式,服务器不需要存储用户会话数据。
-
安全性:
- 签名确保令牌未被篡改。
- 但注意:Payload 可以被解码,因此敏感信息需要加密或避免存储在 JWT 中。
4. JWT 的使用场景
-
用户认证:
- 用户登录成功后,服务器生成一个 JWT,返回给客户端。
- 客户端每次请求时将 JWT 附带在请求头(通常是
Authorization: Bearer <token>
)中。 - 服务器通过验证 JWT 来确定用户身份。
-
授权:
- 用于控制用户对资源的访问权限。
- JWT 中可以包含用户角色或权限信息。
-
单点登录(SSO):
- JWT 是 SSO 的一种理想选择,因其跨平台的特点,可以在不同的服务间传递用户身份。
5. JWT 的生命周期
-
生成:
- 用户向服务器发送登录请求。
- 服务器验证用户身份后生成 JWT,通常会设置过期时间(如 15 分钟)。
- JWT 返回给客户端。
-
验证:
- 客户端在后续请求中发送 JWT。
- 服务器通过签名验证 JWT 是否有效。
-
刷新:
- JWT 的有效期一般较短,若用户需要长期登录,可以结合 Refresh Token 实现令牌刷新。
6. JWT 的优点
- 无状态性:服务器无需存储会话数据。
- 高效性:可以通过单个令牌传递多种信息。
- 跨语言支持:JWT 是一种标准,可以被多种编程语言支持。
7. JWT 的注意事项
-
不要存储敏感数据:
- Payload 是明文可解码的,敏感信息应避免放入 JWT。
-
使用 HTTPS:
- 确保 JWT 在传输过程中被加密,防止被中间人攻击。
-
设置有效期:
- 短生命周期的 JWT 可以减少被盗用的风险。
-
签名密钥管理:
- 确保签名密钥的安全,避免泄漏。
8. JWT 示例
一个完整的 JWT 示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
解码后:
-
Header:
{ "alg": "HS256", "typ": "JWT" }
-
Payload:
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
-
Signature:
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
9. 总结
JWT 是一种高效的认证和授权工具,适合现代 Web 应用。学习 JWT 后,可以轻松实现用户登录、权限控制等功能,为 Web 开发打下坚实基础!
二、java的springboot支持
下面有3个类,这三个类都在同一个包里,构成了一个工具类。可以通过 JwtTokenUtil.java 类直接使用封装好的方法即可。
1. pom依赖
先直接上pom依赖
<!--JWT-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
从Maven的依赖官网搜索了一下,从截图中可以看到有以下四个。
jjwt 是一个包含多个依赖的聚合包,它包括了 jjwt-api、jjwt-impl 和 jjwt-jackson(或 jjwt-gson,取决于你选择的 JSON 处理库)。
- jjwt-api 提供了 JWT 的基本接口和抽象类。
- jjwt-impl 则提供了 JWT 的具体实现,它是运行时依赖。
- jjwt-jackson(或 jjwt-gson)用于 JSON 处理,也是运行时依赖。
因此,当你导入 jjwt 依赖时,实际上是在项目中引入了这三个组件。这样做可以简化依赖管理,因为只需要引入一个依赖即可。
2. application.yaml配置
#JWT 自定义属性
jwt:
# secretKey: 78944878877848fg) # 秘钥
secretKey: fengfanli # 秘钥
accessTokenExpireTime: PT2H # 过期时间 两个小时
refreshTokenExpireTime: PT8H # 刷新token,
refreshTokenExpireAppTime: P30D
issuer: fengfanli.com # 签名:
3. 加载application.yaml配置的配置类
package com.feng.companyframe.jwt;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.contex