JwtUtils工具类
实现功能
个人理解
这个JwtUtils类实现了一系列与JWT(JSON Web Token)相关的功能,主要包括:
生成JWT:类提供了几种方法来生成JWT,可以基于用户的主体信息(如用户名),也可以包括用户的角色权限,以及可以设置自定义的过期时间。
解析JWT:类提供了一个方法来解析传入的JWT,并返回一个Claims对象,这个对象包含了JWT中的所有声明(如主体、过期时间、自定义声明等)。
校验JWT:在解析JWT的过程中,类会自动校验JWT的有效性,包括签名是否正确,以及JWT是否过期。如果JWT无效,方法会抛出异常。
判断JWT是否存在:类提供了一个方法来判断传入的字符串是否是一个有效的JWT,即非空且不是"null"字符串。
配置JWT参数:类使用Spring的@Value注解来从配置文件中读取JWT的密钥和过期时间,这使得这些参数可以在外部进行配置,易于维护和更改。
集成Spring Security:类生成的JWT可以包含用户的角色权限信息,这有助于在Spring Security中实现基于角色的访问控制。
judgeTokenIsExist(String token)
: 判断传入的token是否非空且不是"null"字符串。用于检查客户端是否提供了token。
generateToken(String subject)
: 根据传入的主体信息(通常是用户名或用户ID)生成一个JWT。这个JWT会有一个默认的过期时间。
generateToken(String subject, Collection<? extends GrantedAuthority> authorities)
: 与上一个方法类似,但额外包含了用户的角色权限信息。这些权限会被存储在JWT的一个声明中。
generateToken(String subject, long expireTime)
: 根据传入的主体信息和自定义的过期时间生成JWT。这个方法允许调用者设置JWT的具体过期时间,而不是使用默认值。
getTokenBody(String token)
: 解析传入的JWT并返回一个Claims对象,该对象包含了JWT的所有声明。在解析过程中,会验证JWT的签名和过期时间,如果验证失败,将抛出异常。
备注
token
想象一下,你参加了一个大型游乐园,进入游乐园需要购买门票。这张门票就是你的"token",它证明了你已经付费并有权进入游乐园。
在数字世界中,token就像是这张门票的电子版。它是一段特殊的字符序列,由服务器生成并发放给客户端(比如你的浏览器或手机应用),作为客户端进行某些操作的凭证。
当你使用应用进行登录时,服务器会验证你的用户名和密码。一旦验证通过,服务器就会生成一个token,并把它发送给你的设备。这个token通常包含一些关于你的信息(比如用户ID、角色、权限等),以及一个过期时间,以确保token不会永远有效。
现在,每次你的设备需要向服务器请求受保护的资源或服务时(比如查看你的个人信息、发帖、点赞等),它就会带上这个token。服务器收到请求后,会检查token的有效性,确认你的身份,并决定是否允许你访问请求的资源。
这种机制的好处是,你不需要每次操作都输入用户名和密码,而且token可以随时被服务器撤销,从而提高了系统的安全性。此外,token通常比传统的cookie更安全,因为它们不会被保存在客户端的硬盘上,而是保存在内存中,且不容易被窃取。
JWT
JWT
(JSON Web Token)是一种紧凑且自包含的方式,用于在各方之间以JSON对象的形式安全地传输信息。在Web应用程序中,JWT常用于身份验证和授权,它是一个开放标准(RFC 7519),定义了一种简洁、自包含的方法用于通信双方之间以JSON对象的形式安全地传输信息。
JWT由三部分组成,每部分之间用.分隔,分别是:
Header
(头部):包含JWT的元数据,比如类型(JWT)和所使用的签名算法(如HMAC SHA256或RSA)。
Payload
(负载):包含声明的部分,声明是关于实体(通常是用户)和其他数据的声明。有一些标准的声明(如iss、exp、sub等),也可以包含自定义声明。.Payload部分是JWT的主体,包含了要传递的信息。
Signature
(签名):对前两部分(Header和Payload)使用在Header中指定的算法和密钥进行签名,以确保JWT的有效性和完整性。
完整代码注释
package com.rawchen.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.Date;
/**
* @Description: JWT工具类
* @Date: 2020-09-02
*/
@Component // 表明这个类是一个Spring组件,可以被Spring框架自动扫描和装配
public class JwtUtils {
private static long expireTime; // token的过期时间
private static String secretKey; // 用于签名和解析token的密钥
@Value("${token.secretKey}") // 从配置文件中读取secretKey的值
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
@Value("${token.expireTime}") // 从配置文件中读取expireTime的值
public void setExpireTime(long expireTime) {
this.expireTime = expireTime;
}
/**
* 判断token是否存在
*
* @param token 需要判断的token
* @return 返回token是否存在且不为空
*/
public static boolean judgeTokenIsExist(String token) {
return token != null && !"".equals(token) && !"null".equals(token);
}
/**
* 生成token
*
* @param subject 存放在token中的主体信息(如用户名)
* @return 返回生成的JWT字符串
*/
public static String generateToken(String subject) {
String jwt = Jwts.builder()
.setSubject(subject) // 设置token的主体
.setExpiration(new Date(System.currentTimeMillis() + expireTime)) // 设置过期时间
.signWith(SignatureAlgorithm.HS512, secretKey) // 设置签名算法和密钥
.compact();
return jwt;
}
/**
* 生成带角色权限的token
*
* @param subject 存放在token中的主体信息(如用户名)
* @param authorities 用户的角色权限集合
* @return 返回生成的带有角色权限的JWT字符串
*/
public static String generateToken(String subject, Collection<? extends GrantedAuthority> authorities) {
StringBuilder sb = new StringBuilder();
for (GrantedAuthority authority : authorities) {
sb.append(authority.getAuthority()).append(","); // 拼接用户的所有角色权限
}
String jwt = Jwts.builder()
.setSubject(subject) // 设置token的主体
.claim("authorities", sb.toString()) // 在token中添加角色权限信息
.setExpiration(new Date(System.currentTimeMillis() + expireTime)) // 设置过期时间
.signWith(SignatureAlgorithm.HS512, secretKey) // 设置签名算法和密钥
.compact();
return jwt;
}
/**
* 生成自定义过期时间token
*
* @param subject 存放在token中的主体信息(如用户名)
* @param expireTime 自定义的过期时间
* @return 返回生成的JWT字符串
*/
public static String generateToken(String subject, long expireTime) {
String jwt = Jwts.builder()
.setSubject(subject) // 设置token的主体
.setExpiration(new Date(System.currentTimeMillis() + expireTime)) // 设置过期时间
.signWith(SignatureAlgorithm.HS512, secretKey) // 设置签名算法和密钥
.compact();
return jwt;
}
/**
* 获取tokenBody同时校验token是否有效(无效则会抛出异常)
*
* @param token 需要解析的token
* @return 返回token中的Claims对象,包含token的所有声明
*/
public static Claims getTokenBody(String token) {
Claims claims = Jwts.parser().setSigningKey(secretKey) // 设置解析时的密钥
.parseClaimsJws(token.replace("Bearer", "")) // 解析token
.getBody(); // 获取token中的Claims对象
return claims;
}
}