概述
文章目录
- 一、JWT是什么
- 二、JWT构成
- 三、SpringBoot集成JWT
一、JWT是什么
什么是JWT:Json web token (JWT) 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519)。定义了一种简洁的,自包含的方法用于通信双方之间以JSON对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA或ECDSA的公私秘钥对进行签名。
JWT如何获取访问令牌(token)并用于访问资源(API)流程:1、应用端向权限服务器请求授权;2、权限服务器授权成功向应用端返回一个访问令牌(token);3、应用端使用访问令牌(token)访问受保护的资源(如API)。
二、JWT构成
2.1 JWT是由三段信息构成,将这三段信息文本用“.“连接一起就构成了JWT字符串,一个 Token 分三部分,按顺序为
1.头部(header)
2.载荷(payload)
3.签证(signature)
例如:`eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE1NTgwNjI2OTYsInVzZXJJZCI6IjEifQ.XiI0xjX0izVeJRmhbXN1w1fXKdHB0wsc9teFKq84pclpJt6yS2k0BVXAklHrke_nz6XtcCyi1hgvpn8bf95gwg`。
2.2 header
JWT的头部承载两部分信息:
1.声明类型,这里是JWT
2.声明加密的算法,通常直接使用 HMAC SHA256
JWT里验证和签名使用的算法列表如下:
JWT | 算法名称 |
---|---|
HS256 | HMAC256 |
HS384 | HMAC384 |
HS512 | HMAC512 |
RS256 | RSA256 |
RS384 | RSA384 |
RS512 | RSA512 |
ES256 | ECDSA256 |
ES384 | ECDSA384 |
ES512 | ECDSA512 |
2.3 playload
载荷就是存放有效信息的地方。基本上填两种类型的数据
1.标准中注册的声明的数据;
2.自定义数据;
由这两部分内部做 base64 加密。
标准中注册的声明(建议但不强制使用)
iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
自定义数据:存放我们想放在 token 中存放的 key-value 值;
2.4 signature
JWT的第三部分是一个签证信息,这个签证信息由三部分组成;
base64 加密后的 header 和 base64 加密后的 payload 连接组成的字符串,然后通过 header 中声明的加密方式进行加盐 secret 组合加密,然后就构成了JWT的第三部分
三、SpringBoot集成JWT
3.1 添加依赖:
<!-- jwt核心源码库 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.3.0</version>
</dependency>
<!-- java开发jwt的依赖jar包 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
3.2 创建常量类:
public interface Constants {
/************ utils-jwt ************/
/* jwt密钥的key基数 */
public static String JWT_SECERT = "SSO_JWT_SECERT_KEY";
/* 签发者 */
public static String JWT_ISS_USER = "sxt-frugal-jwt";
/* token认证错误 */
public static int JWT_FAILED_CODE = 500;
/* token超时 */
public static int JWT_EXPIRE_CODE = 504;
/* jwt持续时间 */
public static int JWT_LOGIN_MILLIS = 10 * 60 * 1000;
/* jwt添加head头key */
public static String JWT_HEAD_KEY = "Authorization";
/* MD5加密 盐粒 */
public static String PASSWORD_KEY = "password_salt_key";
/************ sso-login ************/
/* 登陆时间限制(单位:秒) */
public static int SSO_LOGIN_SECOND = 60 * 30;
}
3.3 创建工具类
@Slf4j
public class JWTUtils {
public static final ObjectMapper mapper = new ObjectMapper();
/**
* 生成jwt密钥key
*
* @param algorithm
* @return
*/
private static SecretKey generalKey(String algorithm) {
byte[] secreKey = Base64.decode(Constants.JWT_SECERT);
return new SecretKeySpec(secreKey, 0, secreKey.length, algorithm);
}
/**
* 生成token
*
* @param id jwt唯一标识,主要作为一次性token,避免重放攻击
* @param iss jwt签发者
* @param claims payload中的公开信息一般为用户名
* @param ttlmillis 有效期,单位毫秒
* @return token 一次性token,客户端的有效周期,用户退出或者超时,token失效
*/
public static String createJwt(String id, String iss, String claims, long ttlmillis) {
SignatureAlgorithm algorithm = SignatureAlgorithm.HS256;
long timeMillis = System.currentTimeMillis();
Date curDate = new Date(timeMillis);
JwtBuilder jwtBuilder = Jwts.builder().setId(id).setIssuer(iss).setSubject(claims)
/* 设置签发时间 */
.setIssuedAt(curDate)
/* 设置密钥和算法 */
.signWith(algorithm, JWTUtils.generalKey("AES"));
if (ttlmillis > 0) {
/* 设置token失效时间 */
jwtBuilder.setExpiration(new Date(ttlmillis + timeMillis));
}
return jwtBuilder.compact();
}
/**
* jwt认证
*
* @param token
* @return
*/
public static JwtEntity validateToken(String token) {
JwtEntity jwtEntity = new JwtEntity();
Claims claims = null;
try {
claims = JWTUtils.parseToken(token);
jwtEntity.setStatus(true);
jwtEntity.setClaims(claims);
} catch (Exception e) {
log.error("jwt解析异常:", e);
jwtEntity.setStatus(false);
jwtEntity.setCode(Constants.JWT_FAILED_CODE);
}
return jwtEntity;
}
/**
* 解析token
*
* @param token 服务器给客户端的token
* @return
*/
private static Claims parseToken(String token) {
SecretKey generaKey = JWTUtils.generalKey("AES");
return Jwts.parser().setSigningKey(generaKey).parseClaimsJwt(token).getBody();
}
/**
* 生成subject对象
*
* @param object
* @return
* @throws JsonProcessingException
*/
public static String generalSubject(Object object) throws JsonProcessingException {
return mapper.writeValueAsString(object);
}
/**
* 重新生成jwt
*
* @param jwtEntity
* @return
*/
public static String reInitJwt(JwtEntity jwtEntity) {
Claims claims = jwtEntity.getClaims();
return JWTUtils.createJwt(String.valueOf(System.nanoTime()), Constants.JWT_ISS_USER, claims.getSubject(),
Constants.JWT_LOGIN_MILLIS);
}
3.4 JWT工具类调用
public ResponseEntity getLogin(String phone, String password) {
Map<String, String> login = loginMapper.selectOne(phone);
if (MapUtil.isEmpty(login)) {
return ResponseEnum.FAILED.fail("该用户不存在!");
}
String mdPwd = new HmacUtils(HmacAlgorithms.HMAC_MD5, Constants.PASSWORD_KEY).hmacHex(password);
/* 判断密码是否相同 */
if (mdPwd.equals(login.get("password"))) {
login.remove("password");
String claims = null;
try {
claims = JWTUtils.generalSubject(login);
} catch (JsonProcessingException e) {
log.error("claims 解析json异常!", e);
e.printStackTrace();
}
/* 生成jwt */
String jwt = JWTUtils.createJwt(String.valueOf(System.nanoTime()), phone, claims,
Constants.JWT_LOGIN_MILLIS);
/* 添加jwt到header */
response.addHeader(Constants.JWT_HEAD_KEY, jwt);
/* 缓存phone */
JedisTemplate.getInstance().setStringEx(ThreadUtils.getCurrentThreadId(), Constants.SSO_LOGIN_SECOND, phone);
/* 缓存用户基本信息 */
return ResponseEnum.SUCCESSED.success(login);
}
return ResponseEnum.FAILED.fail("用户名或密码错误!");
}
最后
以上就是无奈大神为你收集整理的SpringBoot集合JWT实现工具类的全部内容,希望文章能够帮你解决SpringBoot集合JWT实现工具类所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复