文章目录
- 一、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构成
复制代码
1
2
3
4
5
6
7
8
9
10
11
122.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 |
复制代码
1
2
3
4
5
6
72.3 playload 载荷就是存放有效信息的地方。基本上填两种类型的数据 1.标准中注册的声明的数据; 2.自定义数据; 由这两部分内部做 base64 加密。 标准中注册的声明(建议但不强制使用)
复制代码
1
2
3
4
5
6
7
8
9
10iss: jwt签发者 sub: jwt所面向的用户 aud: 接收jwt的一方 exp: jwt的过期时间,这个过期时间必须要大于签发时间 nbf: 定义在什么时间之前,该jwt都是不可用的. iat: jwt的签发时间 jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。 自定义数据:存放我们想放在 token 中存放的 key-value 值;
复制代码
1
2
3
42.4 signature JWT的第三部分是一个签证信息,这个签证信息由三部分组成; base64 加密后的 header 和 base64 加密后的 payload 连接组成的字符串,然后通过 header 中声明的加密方式进行加盐 secret 组合加密,然后就构成了JWT的第三部分
三、SpringBoot集成JWT
3.1 添加依赖:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13<!-- 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 创建常量类:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public 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 创建工具类
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96@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工具类调用
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29public 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实现工具类内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复