Skip to content

Commit ee9d024

Browse files
authored
test: add Jwt, SM2Encryption and SM3Password util test. (#310)
增加 JWT、SM2Encryption、SM3Password 的 ut 测试用例
1 parent 36730b1 commit ee9d024

5 files changed

Lines changed: 1195 additions & 1 deletion

File tree

base/src/main/java/com/tinyengine/it/login/utils/JwtUtil.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ public static SecretKey getSecretKey() {
9797
*/
9898
public String generateToken(String username, String roles, String userId,
9999
Object tenants, Integer platformId) {
100-
100+
if(username==null ){
101+
throw new IllegalArgumentException("Username must not be null");
102+
}
101103
Map<String, Object> claims = new HashMap<>();
102104
claims.put("username", username);
103105
claims.put("roles", roles);
@@ -253,6 +255,10 @@ private <T> T getClaimFromToken(String token, String claimName, Class<T> clazz)
253255
* 验证 Token 是否有效(包含黑名单检查和过期检查)
254256
*/
255257
public boolean validateToken(String token) {
258+
if (token == null) {
259+
throw new IllegalArgumentException("Token must not be null or empty");
260+
}
261+
256262
try {
257263
// 检查是否在黑名单中
258264
if (tokenBlacklistService.isTokenBlacklisted(token)) {

base/src/main/java/com/tinyengine/it/login/utils/SM3PasswordUtil.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ public class SM3PasswordUtil {
3535
* SM3 哈希计算
3636
*/
3737
public static String sm3Hash(String data, String salt) throws Exception {
38+
if(data == null || salt == null) {
39+
throw new IllegalArgumentException("数据和盐值不能为空");
40+
}
3841
MessageDigest md = MessageDigest.getInstance(SM3_ALGORITHM, "BC");
3942
String dataWithSalt = data + salt;
4043
byte[] hash = md.digest(dataWithSalt.getBytes("UTF-8"));
@@ -54,6 +57,9 @@ public static PasswordResult createPassword(String plainPassword) throws Excepti
5457
* 验证用户密码
5558
*/
5659
public static boolean verifyPassword(String inputPassword, String storedHash, String salt) throws Exception {
60+
if(inputPassword == null || storedHash == null || salt == null) {
61+
throw new IllegalArgumentException("输入密码、存储哈希和盐值不能为空");
62+
}
5763
String computedHash = sm3Hash(inputPassword, salt);
5864
return computedHash.equals(storedHash);
5965
}
Lines changed: 352 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
package com.tinyengine.it.login.utils;
2+
3+
import cn.hutool.core.util.ReflectUtil;
4+
import com.tinyengine.it.login.service.TokenBlacklistService;
5+
6+
import io.jsonwebtoken.Jwts;
7+
import io.jsonwebtoken.security.Keys;
8+
import org.springframework.core.env.Environment;
9+
import org.junit.jupiter.api.BeforeEach;
10+
import org.junit.jupiter.api.Test;
11+
import org.mockito.InjectMocks;
12+
import org.mockito.Mock;
13+
import org.mockito.MockitoAnnotations;
14+
15+
import javax.crypto.SecretKey;
16+
import java.nio.charset.StandardCharsets;
17+
import java.util.*;
18+
19+
import static org.junit.jupiter.api.Assertions.*;
20+
import static org.mockito.Mockito.when;
21+
22+
class JwtUtilTest {
23+
24+
@Mock
25+
private TokenBlacklistService tokenBlacklistService;
26+
@Mock
27+
private Environment environment;
28+
29+
30+
@InjectMocks
31+
private JwtUtil jwtUtil;
32+
33+
@BeforeEach
34+
void setUp() {
35+
MockitoAnnotations.openMocks(this);
36+
37+
ReflectUtil.setFieldValue(jwtUtil, "tokenBlacklistService", tokenBlacklistService);
38+
ReflectUtil.setFieldValue(jwtUtil, "environment", environment);
39+
String testSecret = "myTestSecretKeyThatIsLongEnoughForHS256Algorithm";
40+
ReflectUtil.setFieldValue(jwtUtil, "cachedSecret", testSecret);
41+
42+
when(environment.getActiveProfiles()).thenReturn("dev".split(","));
43+
// Also set expiration time if it's not a constant but an injected value
44+
45+
}
46+
@Test
47+
void validateSecretConfigurationThrowsExceptionWhenSecretIsMissingInNonDevProfile() {
48+
when(environment.getActiveProfiles()).thenReturn(new String[]{"prod"});
49+
50+
assertThrows(IllegalStateException.class, jwtUtil::validateSecretConfiguration);
51+
}
52+
53+
@Test
54+
void validateSecretConfigurationGeneratesSecretInDevProfile() {
55+
when(environment.getActiveProfiles()).thenReturn(new String[]{"dev"});
56+
assertDoesNotThrow(jwtUtil::validateSecretConfiguration);
57+
}
58+
59+
60+
@Test
61+
void validateSecretConfigurationThrowsExceptionForInvalidSecret() {
62+
when(environment.getActiveProfiles()).thenReturn(new String[]{"prod"});
63+
System.setProperty("SECRET_STRING", "short");
64+
assertThrows(IllegalStateException.class, jwtUtil::validateSecretConfiguration);
65+
}
66+
@Test
67+
void getSecretKeyReturnsValidKey() {
68+
// 使用足够长的密钥(>32字节)
69+
String testSecret = "myTestSecretKeyThatIsLongEnoughForHS256Algorithm";
70+
71+
jwtUtil.validateSecretConfiguration(); // 现在不会 NPE
72+
SecretKey secretKey = jwtUtil.getSecretKey();
73+
74+
assertNotNull(secretKey);
75+
assertEquals("HmacSHA256", secretKey.getAlgorithm());
76+
77+
}
78+
79+
@Test
80+
void generateTokenReturnsValidToken() {
81+
String username = "testUser";
82+
String roles = "USER";
83+
String userId = "123";
84+
Integer platformId = 1;
85+
86+
String token = jwtUtil.generateToken(username, roles, userId, null, platformId);
87+
88+
assertNotNull(token);
89+
assertFalse(token.isEmpty());
90+
assertEquals(username, jwtUtil.getUsernameFromToken(token));
91+
assertEquals(roles, jwtUtil.getRolesFromToken(token));
92+
assertEquals(userId, jwtUtil.getUserIdFromToken(token));
93+
assertEquals(platformId, jwtUtil.getPlatformIdFromToken(token));
94+
}
95+
96+
@Test
97+
void generateTokenThrowsExceptionForNullUsername() {
98+
assertThrows(IllegalArgumentException.class, () -> jwtUtil.generateToken(null, "USER", "123", null, 1),
99+
"Null username should throw IllegalArgumentException");
100+
}
101+
102+
@Test
103+
void generateTokenHandlesEmptyRoles() {
104+
String token = jwtUtil.generateToken("testUser", "", "123", null, 1);
105+
106+
assertNotNull(token);
107+
assertFalse(token.isEmpty());
108+
assertEquals("", jwtUtil.getRolesFromToken(token));
109+
}
110+
111+
@Test
112+
void generateTokenHandlesNullUserId() {
113+
// Given
114+
String username = "testUser";
115+
String roles = "USER";
116+
Integer platformId = 1;
117+
Object tenants = null; // 显式传入 null
118+
// When
119+
String token = jwtUtil.generateToken(username, roles, null, tenants, platformId);
120+
121+
// Then
122+
assertNotNull(token);
123+
assertFalse(token.isEmpty());
124+
125+
// 使用 assertAll 聚合断言,避免单个失败中断其余检查
126+
assertAll("Token claims validation",
127+
() -> assertNull(jwtUtil.getUserIdFromToken(token), "userId should be null"),
128+
() -> assertEquals(username, jwtUtil.getUsernameFromToken(token), "username mismatch"),
129+
() -> assertEquals(roles, jwtUtil.getRolesFromToken(token), "roles mismatch"),
130+
() -> assertEquals(platformId, jwtUtil.getPlatformIdFromToken(token), "platformId mismatch"),
131+
() -> assertEquals(Collections.emptyList(), jwtUtil.getTenantsFromToken(token), "tenants should be empty list")
132+
);
133+
}
134+
135+
@Test
136+
void generateTokenHandlesNullTenants() {
137+
String token = jwtUtil.generateToken("testUser", "USER", "123", null, 1);
138+
139+
assertNotNull(token);
140+
assertFalse(token.isEmpty());
141+
assertTrue(jwtUtil.getTenantsFromToken(token).isEmpty());
142+
}
143+
144+
@Test
145+
void generateTokenHandlesEmptyTenantsList() {
146+
String token = jwtUtil.generateToken("testUser", "USER", "123", new ArrayList<>(), 1);
147+
148+
assertNotNull(token);
149+
assertFalse(token.isEmpty());
150+
assertTrue(jwtUtil.getTenantsFromToken(token).isEmpty());
151+
}
152+
153+
@Test
154+
void generateTokenHandlesNullPlatformId() {
155+
String token = jwtUtil.generateToken("testUser", "USER", "123", null, null);
156+
157+
assertNotNull(token);
158+
assertFalse(token.isEmpty());
159+
assertNull(jwtUtil.getPlatformIdFromToken(token));
160+
}
161+
162+
@Test
163+
void generateTokenHandlesSpecialCharactersInUsername() {
164+
String username = "user!@#$%^&*()";
165+
String token = jwtUtil.generateToken(username, "USER", "123", null, 1);
166+
167+
assertNotNull(token);
168+
assertFalse(token.isEmpty());
169+
assertEquals(username, jwtUtil.getUsernameFromToken(token));
170+
}
171+
172+
@Test
173+
void generateTokenHandlesLongUsername() {
174+
String username = "a".repeat(256);
175+
String token = jwtUtil.generateToken(username, "USER", "123", null, 1);
176+
177+
assertNotNull(token);
178+
assertFalse(token.isEmpty());
179+
assertEquals(username, jwtUtil.getUsernameFromToken(token));
180+
}
181+
182+
@Test
183+
void generateTokenHandlesCombinationOfNullAndValidParameters() {
184+
assertThrows(IllegalArgumentException.class, () -> jwtUtil.generateToken(null, "USER", "123", null, 1),
185+
"Null username should throw IllegalArgumentException");
186+
187+
}
188+
189+
@Test
190+
void validateTokenReturnsTrueForValidToken() {
191+
String token = jwtUtil.generateToken("validUser", "USER", "123", null, 1);
192+
when(tokenBlacklistService.isTokenBlacklisted(token)).thenReturn(false);
193+
194+
boolean isValid = jwtUtil.validateToken(token);
195+
196+
assertTrue(isValid, "Valid token should return true");
197+
}
198+
199+
@Test
200+
void validateTokenReturnsFalseForBlacklistedToken() {
201+
String token = "blacklistedToken";
202+
when(tokenBlacklistService.isTokenBlacklisted(token)).thenReturn(true);
203+
204+
boolean isValid = jwtUtil.validateToken(token);
205+
206+
assertFalse(isValid, "Blacklisted token should return false");
207+
}
208+
209+
@Test
210+
void validateTokenReturnsFalseForExpiredToken() {
211+
String expiredToken = createExpiredToken("expiredUser", "USER", "999");
212+
213+
when(tokenBlacklistService.isTokenBlacklisted(expiredToken)).thenReturn(false);
214+
215+
// Simulate token expiration by waiting or mocking expiration
216+
boolean isValid = jwtUtil.validateToken(expiredToken);
217+
218+
assertFalse(isValid, "Expired token should return false");
219+
}
220+
221+
@Test
222+
void validateTokenReturnsFalseForMalformedToken() {
223+
String malformedToken = "malformedToken";
224+
225+
boolean isValid = jwtUtil.validateToken(malformedToken);
226+
227+
assertFalse(isValid, "Malformed token should return false");
228+
}
229+
230+
@Test
231+
void validateTokenReturnsFalseForInvalidSignature() {
232+
String token = jwtUtil.generateToken("validUser", "USER", "123", null, 1);
233+
String tamperedToken = token + "tampered";
234+
235+
boolean isValid = jwtUtil.validateToken(tamperedToken);
236+
237+
assertFalse(isValid, "Token with invalid signature should return false");
238+
}
239+
240+
@Test
241+
void validateTokenThrowsExceptionForNullToken() {
242+
assertThrows(IllegalArgumentException.class, () -> jwtUtil.validateToken(null),
243+
"Null token should throw IllegalArgumentException");
244+
}
245+
246+
@Test
247+
void validateTokenReturnsFalseForEmptyToken() {
248+
String emptyToken = "";
249+
250+
boolean isValid = jwtUtil.validateToken(emptyToken);
251+
252+
assertFalse(isValid, "Empty token should return false");
253+
}
254+
255+
@Test
256+
void validateTokenReturnsFalseForTokenWithMissingClaims() {
257+
String token = jwtUtil.generateToken("validUser", null, null, null, null);
258+
when(tokenBlacklistService.isTokenBlacklisted(token)).thenReturn(true);
259+
260+
boolean isValid = jwtUtil.validateToken(token);
261+
262+
assertFalse(isValid, "Token with missing claims should return false");
263+
}
264+
265+
@Test
266+
void validateTokenHandlesTokenWithExtraClaims() {
267+
String token = jwtUtil.generateToken("testUser", "USER", "123", null, 1);
268+
// Add extra claims manually
269+
String tokenWithExtraClaims = token + ".extraClaims";
270+
271+
boolean isValid = jwtUtil.validateToken(tokenWithExtraClaims);
272+
273+
assertFalse(isValid, "Token with extra claims should return false");
274+
}
275+
276+
@Test
277+
void validateTokenHandlesTokenWithInvalidExpirationDate() {
278+
String token = jwtUtil.generateToken("testUser", "USER", "123", null, 1);
279+
when(tokenBlacklistService.isTokenBlacklisted(token)).thenReturn(true);
280+
281+
// Simulate invalid expiration date
282+
String tamperedToken = token.replace("exp", "invalidExp");
283+
284+
boolean isValid = jwtUtil.validateToken(tamperedToken);
285+
286+
assertFalse(isValid, "Token with invalid expiration date should return false");
287+
}
288+
289+
@Test
290+
void validateTokenHandlesTokenWithNullClaims() {
291+
String token = jwtUtil.generateToken("testUser", "USER", "123", null, 1);
292+
when(tokenBlacklistService.isTokenBlacklisted(token)).thenReturn(true);
293+
294+
// Simulate null claims
295+
String tamperedToken = token.replace("claims", "null");
296+
297+
boolean isValid = jwtUtil.validateToken(tamperedToken);
298+
299+
assertFalse(isValid, "Token with null claims should return false");
300+
}
301+
302+
@Test
303+
void validateTokenHandlesTokenWithEmptyClaims() {
304+
String token = jwtUtil.generateToken("testUser", "USER", "123", null, 1);
305+
when(tokenBlacklistService.isTokenBlacklisted(token)).thenReturn(true);
306+
307+
// Simulate empty claims
308+
String tamperedToken = token.replace("claims", "{}");
309+
310+
boolean isValid = jwtUtil.validateToken(tamperedToken);
311+
312+
assertFalse(isValid, "Token with empty claims should return false");
313+
}
314+
315+
@Test
316+
void validateTokenHandlesTokenWithInvalidAlgorithm() {
317+
String token = jwtUtil.generateToken("testUser", "USER", "123", null, 1);
318+
when(tokenBlacklistService.isTokenBlacklisted(token)).thenReturn(true);
319+
320+
// Simulate invalid algorithm
321+
String tamperedToken = token.replace("HS256", "RS256");
322+
323+
boolean isValid = jwtUtil.validateToken(tamperedToken);
324+
325+
assertFalse(isValid, "Token with invalid algorithm should return false");
326+
}
327+
328+
/**
329+
* 辅助方法:生成一个已经过期的JWT(不通过JwtUtil,直接使用相同的密钥)
330+
*/
331+
private String createExpiredToken(String username, String roles, String userId) {
332+
Map<String, Object> claims = new HashMap<>();
333+
claims.put("username", username);
334+
claims.put("roles", roles);
335+
claims.put("userId", userId);
336+
claims.put("platformId", 1);
337+
claims.put("tenants", new ArrayList<>());
338+
339+
// 使用与JwtUtil中完全相同的密钥
340+
String testSecret = "myTestSecretKeyThatIsLongEnoughForHS256Algorithm";
341+
SecretKey key = Keys.hmacShaKeyFor(testSecret.getBytes(StandardCharsets.UTF_8));
342+
343+
return Jwts.builder()
344+
.claims(claims)
345+
.subject(username)
346+
.issuedAt(new Date(System.currentTimeMillis() - 120_000)) // 2分钟前签发
347+
.expiration(new Date(System.currentTimeMillis() - 60_000)) // 1分钟前过期
348+
.signWith(key)
349+
.compact();
350+
}
351+
352+
}

0 commit comments

Comments
 (0)