From 249de690e24348a810439ae6841b71546b229af3 Mon Sep 17 00:00:00 2001 From: benjobs Date: Fri, 1 Aug 2025 16:04:08 +0800 Subject: [PATCH 01/26] [CVE] CVE-2025-53960 fixed --- .../src/main/assembly/bin/streampark.sh | 13 +- .../console/base/util/BashJavaUtils.java | 35 ++++ .../system/authentication/JWTFilter.java | 4 +- .../system/authentication/JWTUtil.java | 156 +++++++++++++----- .../system/authentication/ShiroRealm.java | 17 +- .../console/base/util/EncryptUtilsTest.java | 6 +- .../core/service/AccessTokenServiceTest.java | 5 +- .../system/authentication/JWTTest.java | 3 +- 8 files changed, 178 insertions(+), 61 deletions(-) diff --git a/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh b/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh index 5045c78926..af4083ad67 100755 --- a/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh +++ b/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh @@ -360,7 +360,7 @@ start() { fi if [[ "${HADOOP_HOME}"x == ""x ]]; then - echo_y "WARN: HADOOP_HOME is undefined on your system env,please check it." + echo_y "WARN: HADOOP_HOME is undefined on your system env, please check it." else echo_w "Using HADOOP_HOME: ${HADOOP_HOME}" fi @@ -394,6 +394,8 @@ start() { echo_g "JAVA_OPTS: ${JAVA_OPTS}" + jwt_secret + eval $NOHUP $JAVACMD $JAVA_OPTS \ -classpath "$APP_CLASSPATH" \ -Dapp.home="${APP_HOME}" \ @@ -426,7 +428,7 @@ start_docker() { fi if [[ "${HADOOP_HOME}"x == ""x ]]; then - echo_y "WARN: HADOOP_HOME is undefined on your system env,please check it." + echo_y "WARN: HADOOP_HOME is undefined on your system env, please check it." else echo_w "Using HADOOP_HOME: ${HADOOP_HOME}" fi @@ -517,6 +519,13 @@ stop() { fi } +jwt_secret() { + local secret=`$JAVACMD -cp "$APP_LIB/*" $BASH_UTIL --jwt_secret` + if [[ -n "$secret" ]]; then + echo "JWT_SECRET: $secret" + fi +} + status() { # shellcheck disable=SC2155 # shellcheck disable=SC2006 diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java index b1189c290d..5c4e120800 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java @@ -34,7 +34,10 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.PosixFilePermissions; +import java.security.SecureRandom; import java.util.Arrays; +import java.util.Base64; import java.util.Map; public class BashJavaUtils { @@ -46,6 +49,12 @@ public static void main(String[] args) throws IOException { String[] actionArgs = Arrays.copyOfRange(args, 1, args.length); switch (action) { + case "--jwt_secret": + String secret = getFirstOrCreateJWTSecret(); + if (secret != null) { + System.out.println(secret); + } + break; case "--get_yaml": String key = actionArgs[0]; String conf = actionArgs[1]; @@ -129,4 +138,30 @@ public static void main(String[] args) throws IOException { break; } } + + private static String getFirstOrCreateJWTSecret() { + String userHome = System.getProperty("user.home"); + File keyFile = new File(userHome, "streampark.jwt.key"); + if (!keyFile.exists()) { + byte[] bytes = new byte[32]; + new SecureRandom().nextBytes(bytes); + String secret = Base64.getEncoder().encodeToString(bytes); + try { + FileUtils.writeFile(secret, keyFile); + try { + Files.setPosixFilePermissions(Paths.get(keyFile.getAbsolutePath()), + PosixFilePermissions.fromString("rw-------")); + } catch (UnsupportedOperationException e) { + keyFile.setReadable(true, true); + keyFile.setWritable(true, true); + keyFile.setExecutable(false, false); + } + } catch (Exception e) { + throw new SecurityException("Failed to generate JWT key", e); + } + return secret; + } + return null; + } + } diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTFilter.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTFilter.java index d7e81e5734..cebfaa0cf3 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTFilter.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTFilter.java @@ -17,8 +17,6 @@ package org.apache.streampark.console.system.authentication; -import org.apache.streampark.console.base.util.EncryptUtils; - import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; @@ -58,7 +56,7 @@ protected boolean executeLogin(ServletRequest request, ServletResponse response) HttpServletRequest httpServletRequest = (HttpServletRequest) request; String token = httpServletRequest.getHeader(TOKEN); try { - token = EncryptUtils.decrypt(token); + token = JWTUtil.decrypt(token); JWTToken jwtToken = new JWTToken(token); getSubject(request, response).login(jwtToken); return true; diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index f51c276f30..a9bbc8ddad 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -17,10 +17,12 @@ package org.apache.streampark.console.system.authentication; -import org.apache.streampark.console.base.util.EncryptUtils; +import org.apache.streampark.common.util.FileUtils; import org.apache.streampark.console.core.enums.AuthenticationType; import org.apache.streampark.console.system.entity.User; +import org.apache.commons.lang3.StringUtils; + import com.auth0.jwt.JWT; import com.auth0.jwt.JWTCreator; import com.auth0.jwt.JWTVerifier; @@ -28,6 +30,15 @@ import com.auth0.jwt.interfaces.DecodedJWT; import lombok.extern.slf4j.Slf4j; +import javax.crypto.Cipher; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import java.io.File; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; +import java.util.Base64; import java.util.Date; import java.util.regex.Pattern; @@ -36,45 +47,52 @@ public class JWTUtil { private static Long ttlOfSecond; + private static final String ALGORITHM = "AES/GCM/NoPadding"; + private static final int GCM_TAG_LENGTH = 128; + private static final int GCM_IV_LENGTH = 12; + private static final String JWT_USERID = "userId"; private static final String JWT_USERNAME = "userName"; private static final String JWT_TYPE = "type"; private static final String JWT_TIMESTAMP = "timestamp"; - /** - * verify token - * - * @param token token - * @return is valid token - */ - public static boolean verify(String token, String username, String secret) { + private static byte[] JWT_KEY = loadSigningKey(); // 用于 HMAC256 + + private static byte[] loadSigningKey() { + String userHome = System.getProperty("user.home"); + File keyFile = new File(userHome, "streampark.jwt.key"); + String secret = null; + if (keyFile.exists()) { + try { + secret = FileUtils.readFile(keyFile).trim(); + } catch (Exception e) { + log.error("Failed to read JWT key file", e); + } + } + + if (StringUtils.isEmpty(secret)) { + throw new ExceptionInInitializerError("JWT secret initialization failed."); + } try { - Algorithm algorithm = Algorithm.HMAC256(secret); - JWTVerifier verifier = JWT.require(algorithm).withClaim(JWT_USERNAME, username).build(); - verifier.verify(token); - return true; - } catch (Exception ignored) { - return false; + byte[] key = Base64.getDecoder().decode(secret); + if (key.length != 32) { + throw new SecurityException("HMAC key must be 32 bytes"); + } + return key; + } catch (Exception e) { + throw new SecurityException("Invalid JWT secret format", e); } } /** get username from token */ public static String getUserName(String token) { - try { - DecodedJWT jwt = JWT.decode(token); - return jwt.getClaim(JWT_USERNAME).asString(); - } catch (Exception ignored) { - return null; - } + DecodedJWT jwt = decode(token); + return jwt != null ? jwt.getClaim(JWT_USERNAME).asString() : null; } public static Long getUserId(String token) { - try { - DecodedJWT jwt = JWT.decode(token); - return jwt.getClaim(JWT_USERID).asLong(); - } catch (Exception ignored) { - return null; - } + DecodedJWT jwt = decode(token); + return jwt != null ? jwt.getClaim(JWT_USERID).asLong() : null; } /** @@ -82,12 +100,8 @@ public static Long getUserId(String token) { * @return */ public static Long getTimestamp(String token) { - try { - DecodedJWT jwt = JWT.decode(token); - return jwt.getClaim(JWT_TIMESTAMP).asLong(); - } catch (Exception ignored) { - return 0L; - } + DecodedJWT jwt = decode(token); + return jwt != null ? jwt.getClaim(JWT_TIMESTAMP).asLong() : 0L; } /** @@ -95,13 +109,12 @@ public static Long getTimestamp(String token) { * @return */ public static AuthenticationType getAuthType(String token) { - try { - DecodedJWT jwt = JWT.decode(token); - int type = jwt.getClaim(JWT_TYPE).asInt(); - return AuthenticationType.of(type); - } catch (Exception ignored) { + DecodedJWT jwt = decode(token); + if (jwt == null) { return null; } + int type = jwt.getClaim(JWT_TYPE).asInt(); + return AuthenticationType.of(type); } /** @@ -125,7 +138,7 @@ public static String sign(User user, AuthenticationType authType) throws Excepti */ public static String sign(User user, AuthenticationType authType, Long expireTime) throws Exception { Date date = new Date(expireTime); - Algorithm algorithm = Algorithm.HMAC256(user.getPassword()); + Algorithm algorithm = Algorithm.HMAC256(JWT_KEY); JWTCreator.Builder builder = JWT.create() @@ -139,7 +152,7 @@ public static String sign(User user, AuthenticationType authType, Long expireTim } String token = builder.sign(algorithm); - return EncryptUtils.encrypt(token); + return encrypt(token); } public static Long getTTLOfSecond() { @@ -167,4 +180,69 @@ public static Long getTTLOfSecond() { } return ttlOfSecond; } + + private static DecodedJWT decode(String token) { + try { + Algorithm algorithm = Algorithm.HMAC256(JWT_KEY); + JWTVerifier verifier = JWT.require(algorithm).build(); + return verifier.verify(token); + } catch (Exception e) { + return null; + } + } + + public static boolean verify(String token) { + try { + // Base64解码签名密钥 + Algorithm algorithm = Algorithm.HMAC256(JWT_KEY); + JWTVerifier verifier = JWT.require(algorithm).build(); + verifier.verify(decrypt(token)); + return true; + } catch (Exception e) { + log.warn("Invalid JWT: {}", e.getMessage()); + return false; + } + } + + // 修复加密方法 + public static String encrypt(String content) throws Exception { + // 生成随机IV + byte[] iv = new byte[GCM_IV_LENGTH]; + SecureRandom.getInstanceStrong().nextBytes(iv); + + SecretKeySpec keySpec = new SecretKeySpec(JWT_KEY, "AES"); + + // 初始化加密器 + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, new GCMParameterSpec(GCM_TAG_LENGTH, iv)); + + // 加密数据 + byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)); + + // 组合IV + 密文 + ByteBuffer buffer = ByteBuffer.allocate(iv.length + encrypted.length); + buffer.put(iv); + buffer.put(encrypted); + + return Base64.getEncoder().encodeToString(buffer.array()); + } + + public static String decrypt(String content) throws Exception { + byte[] data = Base64.getDecoder().decode(content); + ByteBuffer buffer = ByteBuffer.wrap(data); + + byte[] iv = new byte[GCM_IV_LENGTH]; + buffer.get(iv); + byte[] encrypted = new byte[buffer.remaining()]; + buffer.get(encrypted); + + SecretKeySpec keySpec = new SecretKeySpec(JWT_KEY, "AES"); + + Cipher cipher = Cipher.getInstance(ALGORITHM); + GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv); + cipher.init(Cipher.DECRYPT_MODE, keySpec, spec); + + return new String(cipher.doFinal(encrypted), StandardCharsets.UTF_8); + } + } diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroRealm.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroRealm.java index 6ea9d88a48..6c65334d4f 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroRealm.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroRealm.java @@ -18,7 +18,6 @@ package org.apache.streampark.console.system.authentication; import org.apache.streampark.common.util.SystemPropertyUtils; -import org.apache.streampark.console.base.util.EncryptUtils; import org.apache.streampark.console.core.enums.AuthenticationType; import org.apache.streampark.console.system.entity.AccessToken; import org.apache.streampark.console.system.entity.User; @@ -90,6 +89,12 @@ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authent throw new AuthenticationException("the authorization token is invalid"); } + // Query user information by username + User user = userService.getByUsername(username); + if (user == null || !user.getUserId().equals(userId)) { + throw new AuthenticationException("the authorization token verification failed."); + } + switch (authType) { case SIGN: Long timestamp = JWTUtil.getTimestamp(credential); @@ -102,7 +107,7 @@ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authent // Check whether the token belongs to the api and whether the permission is valid AccessToken accessToken = accessTokenService.getByUserId(userId); try { - String encryptToken = EncryptUtils.encrypt(credential); + String encryptToken = JWTUtil.encrypt(credential); if (accessToken == null || !accessToken.getToken().equals(encryptToken)) { throw new AuthenticationException("the openapi authorization token is invalid"); } @@ -112,7 +117,7 @@ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authent if (AccessToken.STATUS_DISABLE.equals(accessToken.getStatus())) { throw new AuthenticationException( - "the openapi authorization token is disabled, please contact the administrator"); + "The OpenAPI authorization token is disabled. Please contact the administrator."); } if (User.STATUS_LOCK.equals(accessToken.getUserStatus())) { @@ -125,12 +130,6 @@ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authent break; } - // Query user information by username - User user = userService.getByUsername(username); - if (user == null || !JWTUtil.verify(credential, username, user.getPassword())) { - throw new AuthenticationException("the authorization token verification failed."); - } - return new SimpleAuthenticationInfo(credential, credential, "streampark_shiro_realm"); } } diff --git a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/base/util/EncryptUtilsTest.java b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/base/util/EncryptUtilsTest.java index 6563b94e36..692afc0698 100644 --- a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/base/util/EncryptUtilsTest.java +++ b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/base/util/EncryptUtilsTest.java @@ -17,7 +17,7 @@ package org.apache.streampark.console.base.util; -import org.apache.streampark.common.constants.Constants; +import org.apache.streampark.console.system.authentication.JWTUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -27,8 +27,8 @@ class EncryptUtilsTest { @Test void testEncrypt() throws Exception { String value = "apache streampark"; - String encrypt = EncryptUtils.encrypt(value, Constants.STREAM_PARK); - String decrypt = EncryptUtils.decrypt(encrypt, Constants.STREAM_PARK); + String encrypt = JWTUtil.encrypt(value); + String decrypt = JWTUtil.decrypt(encrypt); Assertions.assertEquals(value, decrypt); } } diff --git a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/AccessTokenServiceTest.java b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/AccessTokenServiceTest.java index c5de0d6a2f..ad802924d4 100644 --- a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/AccessTokenServiceTest.java +++ b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/AccessTokenServiceTest.java @@ -20,7 +20,6 @@ import org.apache.streampark.console.SpringUnitTestBase; import org.apache.streampark.console.base.domain.RestRequest; import org.apache.streampark.console.base.domain.RestResponse; -import org.apache.streampark.console.base.util.EncryptUtils; import org.apache.streampark.console.system.authentication.JWTToken; import org.apache.streampark.console.system.authentication.JWTUtil; import org.apache.streampark.console.system.entity.AccessToken; @@ -51,14 +50,14 @@ void testCrudToken() throws Exception { // verify AccessToken accessToken = (AccessToken) restResponse.get("data"); LOG.info(accessToken.getToken()); - JWTToken jwtToken = new JWTToken(EncryptUtils.decrypt(accessToken.getToken())); + JWTToken jwtToken = new JWTToken(JWTUtil.decrypt(accessToken.getToken())); LOG.info(jwtToken.getToken()); String username = JWTUtil.getUserName(jwtToken.getToken()); Assertions.assertNotNull(username); Assertions.assertEquals("admin", username); User user = userService.getByUsername(username); Assertions.assertNotNull(user); - Assertions.assertTrue(JWTUtil.verify(jwtToken.getToken(), username, user.getPassword())); + Assertions.assertTrue(JWTUtil.verify(jwtToken.getToken())); // list AccessToken mockToken1 = new AccessToken(); diff --git a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/system/authentication/JWTTest.java b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/system/authentication/JWTTest.java index ff3ea0bb12..66c67d92b3 100644 --- a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/system/authentication/JWTTest.java +++ b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/system/authentication/JWTTest.java @@ -19,7 +19,6 @@ import org.apache.streampark.common.util.DateUtils; import org.apache.streampark.console.SpringUnitTestBase; -import org.apache.streampark.console.base.util.EncryptUtils; import org.apache.streampark.console.core.enums.AuthenticationType; import org.apache.streampark.console.system.entity.User; @@ -47,7 +46,7 @@ void testExpireTime() throws Exception { AuthenticationType.SIGN, DateUtils.getTime(ttl, DateUtils.fullFormat(), TimeZone.getDefault())); assert token != null; - Date expiresAt = JWT.decode(EncryptUtils.decrypt(token)).getExpiresAt(); + Date expiresAt = JWT.decode(JWTUtil.decrypt(token)).getExpiresAt(); String decodeExpireTime = DateUtils.format(expiresAt, DateUtils.fullFormat(), TimeZone.getDefault()); Assertions.assertEquals(ttl, decodeExpireTime); From beed2b8b8a6134d5fd51992bf17a7fd2c8e8e3d2 Mon Sep 17 00:00:00 2001 From: benjobs Date: Fri, 1 Aug 2025 16:11:35 +0800 Subject: [PATCH 02/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index a9bbc8ddad..a64c6021ec 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -193,7 +193,7 @@ private static DecodedJWT decode(String token) { public static boolean verify(String token) { try { - // Base64解码签名密钥 + // Decode the signing key using Base64 Algorithm algorithm = Algorithm.HMAC256(JWT_KEY); JWTVerifier verifier = JWT.require(algorithm).build(); verifier.verify(decrypt(token)); From c2c9fbc034714392412804cb72841594f4763648 Mon Sep 17 00:00:00 2001 From: benjobs Date: Fri, 1 Aug 2025 16:11:43 +0800 Subject: [PATCH 03/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index a64c6021ec..4c40932676 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -56,7 +56,7 @@ public class JWTUtil { private static final String JWT_TYPE = "type"; private static final String JWT_TIMESTAMP = "timestamp"; - private static byte[] JWT_KEY = loadSigningKey(); // 用于 HMAC256 + private static byte[] JWT_KEY = loadSigningKey(); // Used for HMAC256 private static byte[] loadSigningKey() { String userHome = System.getProperty("user.home"); From 09af5cd3e629e165314379d32a79ac47b1d15830 Mon Sep 17 00:00:00 2001 From: benjobs Date: Fri, 1 Aug 2025 16:11:55 +0800 Subject: [PATCH 04/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index 4c40932676..492affb78b 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -204,7 +204,7 @@ public static boolean verify(String token) { } } - // 修复加密方法 + // Fix encryption method public static String encrypt(String content) throws Exception { // 生成随机IV byte[] iv = new byte[GCM_IV_LENGTH]; From 268b5112b09f7b6831b8f82d08393c55b4f1fc89 Mon Sep 17 00:00:00 2001 From: benjobs Date: Fri, 1 Aug 2025 16:12:05 +0800 Subject: [PATCH 05/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index 492affb78b..1599a1b501 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -206,7 +206,7 @@ public static boolean verify(String token) { // Fix encryption method public static String encrypt(String content) throws Exception { - // 生成随机IV + // Generate a random IV byte[] iv = new byte[GCM_IV_LENGTH]; SecureRandom.getInstanceStrong().nextBytes(iv); From 4f9eaac959b6fcf48b7b8fa1f3acafadba5e917f Mon Sep 17 00:00:00 2001 From: benjobs Date: Fri, 1 Aug 2025 16:12:13 +0800 Subject: [PATCH 06/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index 1599a1b501..dd90f3f976 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -212,7 +212,7 @@ public static String encrypt(String content) throws Exception { SecretKeySpec keySpec = new SecretKeySpec(JWT_KEY, "AES"); - // 初始化加密器 + // Initialize the cipher Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, keySpec, new GCMParameterSpec(GCM_TAG_LENGTH, iv)); From 1cc4a1e008b90bb8702368db980567a56196f804 Mon Sep 17 00:00:00 2001 From: benjobs Date: Fri, 1 Aug 2025 16:12:20 +0800 Subject: [PATCH 07/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index dd90f3f976..36e6312468 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -216,7 +216,7 @@ public static String encrypt(String content) throws Exception { Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, keySpec, new GCMParameterSpec(GCM_TAG_LENGTH, iv)); - // 加密数据 + // Encrypt data byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)); // 组合IV + 密文 From db983bcdcb01a514e5273bafa9a15deb1716aaea Mon Sep 17 00:00:00 2001 From: benjobs Date: Fri, 1 Aug 2025 16:12:39 +0800 Subject: [PATCH 08/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index 36e6312468..f7ee29f9bc 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -219,7 +219,7 @@ public static String encrypt(String content) throws Exception { // Encrypt data byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)); - // 组合IV + 密文 + // Combine IV and ciphertext ByteBuffer buffer = ByteBuffer.allocate(iv.length + encrypted.length); buffer.put(iv); buffer.put(encrypted); From a228ecd4419603b68d7b2845f865cd818605b1c2 Mon Sep 17 00:00:00 2001 From: benjobs Date: Fri, 1 Aug 2025 19:53:34 +0800 Subject: [PATCH 09/26] [Improve] set file permission improvement --- .../apache/streampark/console/base/util/BashJavaUtils.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java index 5c4e120800..c668572169 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java @@ -149,12 +149,11 @@ private static String getFirstOrCreateJWTSecret() { try { FileUtils.writeFile(secret, keyFile); try { - Files.setPosixFilePermissions(Paths.get(keyFile.getAbsolutePath()), + Files.setPosixFilePermissions( + Paths.get(keyFile.getAbsolutePath()), PosixFilePermissions.fromString("rw-------")); } catch (UnsupportedOperationException e) { - keyFile.setReadable(true, true); - keyFile.setWritable(true, true); - keyFile.setExecutable(false, false); + System.err.println("Warning: setPosixFilePermissions for " + keyFile.getAbsolutePath()); } } catch (Exception e) { throw new SecurityException("Failed to generate JWT key", e); From bf8219b8c9626b80f5f1ec6bb3fc224457ca1dcc Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 00:43:54 +0800 Subject: [PATCH 10/26] [Improve] minor improvement --- .../src/main/assembly/bin/streampark.sh | 9 -- .../console/base/util/BashJavaUtils.java | 33 ----- .../system/authentication/JWTSecret.java | 123 ++++++++++++++++++ .../system/authentication/JWTUtil.java | 33 +---- 4 files changed, 124 insertions(+), 74 deletions(-) create mode 100644 streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java diff --git a/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh b/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh index af4083ad67..4d9ec7caad 100755 --- a/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh +++ b/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh @@ -394,8 +394,6 @@ start() { echo_g "JAVA_OPTS: ${JAVA_OPTS}" - jwt_secret - eval $NOHUP $JAVACMD $JAVA_OPTS \ -classpath "$APP_CLASSPATH" \ -Dapp.home="${APP_HOME}" \ @@ -519,13 +517,6 @@ stop() { fi } -jwt_secret() { - local secret=`$JAVACMD -cp "$APP_LIB/*" $BASH_UTIL --jwt_secret` - if [[ -n "$secret" ]]; then - echo "JWT_SECRET: $secret" - fi -} - status() { # shellcheck disable=SC2155 # shellcheck disable=SC2006 diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java index c668572169..adc87f2dd8 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java @@ -34,10 +34,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.PosixFilePermissions; -import java.security.SecureRandom; import java.util.Arrays; -import java.util.Base64; import java.util.Map; public class BashJavaUtils { @@ -49,12 +46,6 @@ public static void main(String[] args) throws IOException { String[] actionArgs = Arrays.copyOfRange(args, 1, args.length); switch (action) { - case "--jwt_secret": - String secret = getFirstOrCreateJWTSecret(); - if (secret != null) { - System.out.println(secret); - } - break; case "--get_yaml": String key = actionArgs[0]; String conf = actionArgs[1]; @@ -139,28 +130,4 @@ public static void main(String[] args) throws IOException { } } - private static String getFirstOrCreateJWTSecret() { - String userHome = System.getProperty("user.home"); - File keyFile = new File(userHome, "streampark.jwt.key"); - if (!keyFile.exists()) { - byte[] bytes = new byte[32]; - new SecureRandom().nextBytes(bytes); - String secret = Base64.getEncoder().encodeToString(bytes); - try { - FileUtils.writeFile(secret, keyFile); - try { - Files.setPosixFilePermissions( - Paths.get(keyFile.getAbsolutePath()), - PosixFilePermissions.fromString("rw-------")); - } catch (UnsupportedOperationException e) { - System.err.println("Warning: setPosixFilePermissions for " + keyFile.getAbsolutePath()); - } - } catch (Exception e) { - throw new SecurityException("Failed to generate JWT key", e); - } - return secret; - } - return null; - } - } diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java new file mode 100644 index 0000000000..948ffaec6c --- /dev/null +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.streampark.console.system.authentication; + +import org.apache.streampark.common.util.FileUtils; + +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.PosixFilePermissions; +import java.security.SecureRandom; +import java.util.Base64; + +@Slf4j +public class JWTSecret { + + private static final int KEY_LENGTH = 32; + + public static byte[] getJWTSecret() { + Path keyPath = Paths.get(System.getProperty("user.home"), "streampark.jwt.key"); + File keyFile = keyPath.toFile(); + + // 尝试加载现有密钥 + byte[] keyBytes = loadExistingKey(keyFile); + if (keyBytes != null) { + return keyBytes; + } + + // 生成新密钥 + keyBytes = generateNewKey(); + saveNewKey(keyBytes, keyPath); + return keyBytes; + } + + private static byte[] loadExistingKey(File keyFile) { + if (!keyFile.exists()) { + return null; + } + + try { + String secret = FileUtils.readFile(keyFile).trim(); + byte[] keyBytes = Base64.getDecoder().decode(secret); + + if (keyBytes.length != KEY_LENGTH) { + log.error("Invalid HMAC key length: {} bytes (expected {} bytes)", keyBytes.length, KEY_LENGTH); + return null; + } + return keyBytes; + } catch (Exception e) { + log.error("Failed to read JWT key file", e); + } + // 清理无效文件 + safelyDeleteFile(keyFile); + return null; + } + + private static byte[] generateNewKey() { + byte[] key = new byte[KEY_LENGTH]; + new SecureRandom().nextBytes(key); + return key; + } + + private static void saveNewKey(byte[] keyBytes, Path keyPath) { + String encodedKey = Base64.getEncoder().encodeToString(keyBytes); + try { + // 确保目录存在 + Files.createDirectories(keyPath.getParent()); + // 安全写入临时文件后重命名 + Path tempFile = Files.createTempFile(keyPath.getParent(), "streampark", ".tmp"); + Files.write(tempFile, encodedKey.getBytes(StandardCharsets.UTF_8)); + + // 设置权限后原子移动 + setStrictPermissions(tempFile); + Files.move(tempFile, keyPath, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING); + + } catch (Exception e) { + throw new SecurityException("Failed to generate JWT key", e); + } + } + + private static void setStrictPermissions(Path path) { + try { + Files.setPosixFilePermissions(path, + PosixFilePermissions.fromString("rw-------")); + } catch (UnsupportedOperationException e) { + log.warn("POSIX permissions not supported for {}", path); + } catch (IOException e) { + log.error("Failed to set permissions for {}", path, e); + } + } + + private static void safelyDeleteFile(File keyFile) { + try { + if (keyFile.exists() && !keyFile.delete()) { + log.warn("Failed to delete invalid key file: {}", keyFile.getAbsolutePath()); + } + } catch (SecurityException e) { + log.error("Security exception when deleting key file", e); + } + } + +} diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index f7ee29f9bc..2d6cde0669 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -17,12 +17,9 @@ package org.apache.streampark.console.system.authentication; -import org.apache.streampark.common.util.FileUtils; import org.apache.streampark.console.core.enums.AuthenticationType; import org.apache.streampark.console.system.entity.User; -import org.apache.commons.lang3.StringUtils; - import com.auth0.jwt.JWT; import com.auth0.jwt.JWTCreator; import com.auth0.jwt.JWTVerifier; @@ -34,7 +31,6 @@ import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; -import java.io.File; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; @@ -50,39 +46,12 @@ public class JWTUtil { private static final String ALGORITHM = "AES/GCM/NoPadding"; private static final int GCM_TAG_LENGTH = 128; private static final int GCM_IV_LENGTH = 12; - private static final String JWT_USERID = "userId"; private static final String JWT_USERNAME = "userName"; private static final String JWT_TYPE = "type"; private static final String JWT_TIMESTAMP = "timestamp"; - private static byte[] JWT_KEY = loadSigningKey(); // Used for HMAC256 - - private static byte[] loadSigningKey() { - String userHome = System.getProperty("user.home"); - File keyFile = new File(userHome, "streampark.jwt.key"); - String secret = null; - if (keyFile.exists()) { - try { - secret = FileUtils.readFile(keyFile).trim(); - } catch (Exception e) { - log.error("Failed to read JWT key file", e); - } - } - - if (StringUtils.isEmpty(secret)) { - throw new ExceptionInInitializerError("JWT secret initialization failed."); - } - try { - byte[] key = Base64.getDecoder().decode(secret); - if (key.length != 32) { - throw new SecurityException("HMAC key must be 32 bytes"); - } - return key; - } catch (Exception e) { - throw new SecurityException("Invalid JWT secret format", e); - } - } + private static byte[] JWT_KEY = JWTSecret.getJWTSecret(); // Used for HMAC256 /** get username from token */ public static String getUserName(String token) { From 1c8a2f229615e208dde7b291b173e317699feb34 Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 00:47:47 +0800 Subject: [PATCH 11/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTSecret.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java index 948ffaec6c..391ccc8f8b 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java @@ -41,7 +41,7 @@ public static byte[] getJWTSecret() { Path keyPath = Paths.get(System.getProperty("user.home"), "streampark.jwt.key"); File keyFile = keyPath.toFile(); - // 尝试加载现有密钥 + // Try to load existing key byte[] keyBytes = loadExistingKey(keyFile); if (keyBytes != null) { return keyBytes; From fd0bb406539940b414896d160e49b9bd607769dc Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 00:47:58 +0800 Subject: [PATCH 12/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTSecret.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java index 391ccc8f8b..4646ad0fdb 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java @@ -47,7 +47,7 @@ public static byte[] getJWTSecret() { return keyBytes; } - // 生成新密钥 + // Generate new key keyBytes = generateNewKey(); saveNewKey(keyBytes, keyPath); return keyBytes; From d44730671a12d05c6653d0af70ddd9996a244947 Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 00:48:07 +0800 Subject: [PATCH 13/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTSecret.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java index 4646ad0fdb..90e66207a4 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java @@ -70,7 +70,7 @@ private static byte[] loadExistingKey(File keyFile) { } catch (Exception e) { log.error("Failed to read JWT key file", e); } - // 清理无效文件 + // Clean up invalid file safelyDeleteFile(keyFile); return null; } From 221ffb843b34ca1809a97b0dadaa5c2b6dbbb160 Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 00:48:35 +0800 Subject: [PATCH 14/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../console/system/authentication/JWTUtil.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index 2d6cde0669..0db7980ca2 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -173,7 +173,15 @@ public static boolean verify(String token) { } } - // Fix encryption method + /** + * Encrypts the given content using AES-GCM with a randomly generated IV. + * The IV is prepended to the ciphertext and the result is Base64-encoded. + * This allows the decrypt method to extract the IV and correctly decrypt the content. + * + * @param content the plaintext string to encrypt + * @return the Base64-encoded string containing the IV and ciphertext + * @throws Exception if encryption fails + */ public static String encrypt(String content) throws Exception { // Generate a random IV byte[] iv = new byte[GCM_IV_LENGTH]; From 484fdb34e7f3bca65de8932920bdad131c83281e Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 00:48:55 +0800 Subject: [PATCH 15/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTSecret.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java index 90e66207a4..6ff2ef72cb 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java @@ -90,7 +90,7 @@ private static void saveNewKey(byte[] keyBytes, Path keyPath) { Path tempFile = Files.createTempFile(keyPath.getParent(), "streampark", ".tmp"); Files.write(tempFile, encodedKey.getBytes(StandardCharsets.UTF_8)); - // 设置权限后原子移动 + // Atomically move after setting permissions setStrictPermissions(tempFile); Files.move(tempFile, keyPath, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING); From b87fa25b4357eb0d62c9d8c46e8c7d1a5fa58092 Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 00:49:01 +0800 Subject: [PATCH 16/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTSecret.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java index 6ff2ef72cb..420c9f5f47 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java @@ -86,7 +86,7 @@ private static void saveNewKey(byte[] keyBytes, Path keyPath) { try { // 确保目录存在 Files.createDirectories(keyPath.getParent()); - // 安全写入临时文件后重命名 + // Safely write to a temporary file before renaming Path tempFile = Files.createTempFile(keyPath.getParent(), "streampark", ".tmp"); Files.write(tempFile, encodedKey.getBytes(StandardCharsets.UTF_8)); From 69ace27566421cfcb1c3809af6781f0dbc265633 Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 00:49:12 +0800 Subject: [PATCH 17/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTSecret.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java index 420c9f5f47..bb8fb73091 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTSecret.java @@ -84,7 +84,7 @@ private static byte[] generateNewKey() { private static void saveNewKey(byte[] keyBytes, Path keyPath) { String encodedKey = Base64.getEncoder().encodeToString(keyBytes); try { - // 确保目录存在 + // Ensure the directory exists Files.createDirectories(keyPath.getParent()); // Safely write to a temporary file before renaming Path tempFile = Files.createTempFile(keyPath.getParent(), "streampark", ".tmp"); From 76271465fdcf14e303f56e2055d90efe2bb8a9fb Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 00:49:42 +0800 Subject: [PATCH 18/26] Update streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../streampark/console/system/authentication/JWTUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index 0db7980ca2..68cef9c977 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -185,7 +185,7 @@ public static boolean verify(String token) { public static String encrypt(String content) throws Exception { // Generate a random IV byte[] iv = new byte[GCM_IV_LENGTH]; - SecureRandom.getInstanceStrong().nextBytes(iv); + SECURE_RANDOM.nextBytes(iv); SecretKeySpec keySpec = new SecretKeySpec(JWT_KEY, "AES"); From 419d3c034014cede67a7e0006cc757dcdb29e57f Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 07:07:24 +0800 Subject: [PATCH 19/26] [CI] dorny/paths-filter@v3.0.2 issue fixed --- .github/actions/paths-filter/action.yml | 33 ++++++++ .github/actions/paths-filter/filter.sh | 101 ++++++++++++++++++++++++ .github/workflows/backend.yml | 4 +- .github/workflows/docs.yml | 6 +- .github/workflows/e2e.yml | 4 +- .github/workflows/frontend.yml | 4 +- .github/workflows/unit-test.yml | 4 +- 7 files changed, 145 insertions(+), 11 deletions(-) create mode 100644 .github/actions/paths-filter/action.yml create mode 100644 .github/actions/paths-filter/filter.sh diff --git a/.github/actions/paths-filter/action.yml b/.github/actions/paths-filter/action.yml new file mode 100644 index 0000000000..16bbd002a0 --- /dev/null +++ b/.github/actions/paths-filter/action.yml @@ -0,0 +1,33 @@ +name: Paths Filter (Multi-Rule) +description: Filter changed files by path patterns, supports wildcards and exclusion. Replacement for dorny/paths-filter in restricted environments. +inputs: + filters: + description: | + Multi-line string defining filter groups. Supports: + - Wildcards: *, **, ? + - Exclusion: !pattern + Example: + backend: + - 'src/**' + - '!**/*.md' + docs: + - '**/*.md' + frontend: + - 'web/**' + - 'assets/**' + config: + - 'pom.xml' + - 'workflow/**' + required: true + +runs: + using: "composite" + steps: + - name: Run path filter + id: run + shell: bash + env: + INPUT_FILTERS: ${{ inputs.filters }} + run: | + chmod +x ${{ github.action_path }}/filter.sh + ${{ github.action_path }}/filter.sh diff --git a/.github/actions/paths-filter/filter.sh b/.github/actions/paths-filter/filter.sh new file mode 100644 index 0000000000..d2ff35f8f5 --- /dev/null +++ b/.github/actions/paths-filter/filter.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +# =================================================================== +# Paths Filter - Multi-rule file change detector +# Replacement for dorny/paths-filter for GitHub Enterprise environments +# Supports: *, **, ?, !pattern, PR/push detection +# =================================================================== + +get_changed_files() { + local base head + if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then + base=${{ github.event.pull_request.base.sha }} + head=${{ github.event.pull_request.head.sha }} + else + base=${{ github.event.before }} + head=${GITHUB_SHA} + if [ "$base" = "0000000000000000000000000000000000000000" ] || [ -z "$base" ]; then + base="HEAD~1" + fi + fi + + echo "::debug::Fetching base=$base, head=$head" + git fetch --depth=1 origin "$base" || git fetch --depth=1 --no-tags "$base" + git fetch --depth=1 origin "$head" || git fetch --depth=1 --no-tags "$head" + + git diff --name-only "$base" "$head" || echo "" +} + +match_pattern() { + local file=$1 + local pattern=$2 + local negate=false + + [[ $pattern == !* ]] && negate=true && pattern="${pattern#!}" + + local regex="^" + local i c + for (( i=0; i<${#pattern}; i++ )); do + c="${pattern:$i:1}" + case "$c" in + "*") regex+=".*" ;; + "?") regex+="." ;; + ".") regex+="\." ;; + "/") regex+="/?" ;; + *) regex+="$c" ;; + esac + done + regex+="$" + + [[ $file =~ $regex ]] && result=true || result=false + + if [ "$negate" = "true" ]; then + [ "$result" = "false" ] + else + [ "$result" = "true" ] + fi +} + +main() { + local filters="$INPUT_FILTERS" + local changed_files + mapfile -t changed_files < <(get_changed_files) + + echo "📄 Found $((${#changed_files[@]})) changed files" + for file in "${changed_files[@]}"; do + [ -n "$file" ] && echo " $file" + done + + local current_group="" + local lines + mapfile -t lines <<< "$filters" + + declare -A group_match + + for line in "${lines[@]}"; do + [[ -z "$line" ]] && continue + + if [[ $line =~ ^[[:space:]]*([a-zA-Z0-9_-]+):[[:space:]]*$ ]]; then + current_group="${BASH_REMATCH[1]}" + group_match["$current_group"]=false + elif [[ $line =~ ^[[:space:]]*-[[:space:]]*[\'\"]?(.*[^\'\"])[\'\"]?[[:space:]]*$ ]]; then + local pattern="${BASH_REMATCH[1]}" + pattern="${pattern%\"}" && pattern="${pattern%\'}" + pattern="${pattern#\"}" && pattern="${pattern#\'}" + + for file in "${changed_files[@]}"; do + if [ -n "$file" ] && match_pattern "$file" "$pattern"; then + group_match["$current_group"]=true + echo "::debug::Match: '$file' ~ '$pattern' => $current_group=true" + fi + done + fi + done + + for group in "${!group_match[@]}"; do + echo "$group=${group_match[$group]}" >> $GITHUB_OUTPUT + echo "::debug::Output: $group=${group_match[$group]}" + done +} + +main "$@" diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 8ea6222e72..13c667125a 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -43,11 +43,11 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 - - uses: dorny/paths-filter@v3.0.2 + - uses: ./.github/actions/paths-filter id: filter with: filters: | - not-ignore: + docs: - '!**/*.md' license-header: name: License header diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 225181d3cc..26807948f3 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -43,12 +43,12 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 - - uses: dorny/paths-filter@v3.0.2 + - uses: ./.github/actions/paths-filter id: filter with: filters: | - not-ignore: - - '**.md' + docs: + - '!**/*.md' license-header: name: License header runs-on: ubuntu-latest diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 4582dafc02..71c7189736 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -38,11 +38,11 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 - - uses: dorny/paths-filter@v3.0.2 + - uses: ./.github/actions/paths-filter id: filter with: filters: | - not-ignore: + docs: - '!**/*.md' license-header: name: License header diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 8691618318..f448fdc842 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -38,11 +38,11 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 - - uses: dorny/paths-filter@v3.0.2 + - uses: ./.github/actions/paths-filter id: filter with: filters: | - not-ignore: + docs: - '!**/*.md' build: name: Build diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 3359cde54f..47c2be407a 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -43,11 +43,11 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 - - uses: dorny/paths-filter@v3.0.2 + - uses: ./.github/actions/paths-filter id: filter with: filters: | - not-ignore: + docs: - '!**/*.md' license-header: name: License header From e02fabdf2d7470250956d01d73b9534cb37be6b5 Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 07:12:43 +0800 Subject: [PATCH 20/26] [Improve] paths-filter improvement --- .github/actions/paths-filter/action.yml | 33 -------- .github/actions/paths-filter/filter.sh | 101 ------------------------ .github/workflows/backend.yml | 6 -- .github/workflows/docs.yml | 6 -- .github/workflows/e2e.yml | 6 -- .github/workflows/frontend.yml | 6 -- .github/workflows/unit-test.yml | 6 -- 7 files changed, 164 deletions(-) delete mode 100644 .github/actions/paths-filter/action.yml delete mode 100644 .github/actions/paths-filter/filter.sh diff --git a/.github/actions/paths-filter/action.yml b/.github/actions/paths-filter/action.yml deleted file mode 100644 index 16bbd002a0..0000000000 --- a/.github/actions/paths-filter/action.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Paths Filter (Multi-Rule) -description: Filter changed files by path patterns, supports wildcards and exclusion. Replacement for dorny/paths-filter in restricted environments. -inputs: - filters: - description: | - Multi-line string defining filter groups. Supports: - - Wildcards: *, **, ? - - Exclusion: !pattern - Example: - backend: - - 'src/**' - - '!**/*.md' - docs: - - '**/*.md' - frontend: - - 'web/**' - - 'assets/**' - config: - - 'pom.xml' - - 'workflow/**' - required: true - -runs: - using: "composite" - steps: - - name: Run path filter - id: run - shell: bash - env: - INPUT_FILTERS: ${{ inputs.filters }} - run: | - chmod +x ${{ github.action_path }}/filter.sh - ${{ github.action_path }}/filter.sh diff --git a/.github/actions/paths-filter/filter.sh b/.github/actions/paths-filter/filter.sh deleted file mode 100644 index d2ff35f8f5..0000000000 --- a/.github/actions/paths-filter/filter.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/bash - -# =================================================================== -# Paths Filter - Multi-rule file change detector -# Replacement for dorny/paths-filter for GitHub Enterprise environments -# Supports: *, **, ?, !pattern, PR/push detection -# =================================================================== - -get_changed_files() { - local base head - if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then - base=${{ github.event.pull_request.base.sha }} - head=${{ github.event.pull_request.head.sha }} - else - base=${{ github.event.before }} - head=${GITHUB_SHA} - if [ "$base" = "0000000000000000000000000000000000000000" ] || [ -z "$base" ]; then - base="HEAD~1" - fi - fi - - echo "::debug::Fetching base=$base, head=$head" - git fetch --depth=1 origin "$base" || git fetch --depth=1 --no-tags "$base" - git fetch --depth=1 origin "$head" || git fetch --depth=1 --no-tags "$head" - - git diff --name-only "$base" "$head" || echo "" -} - -match_pattern() { - local file=$1 - local pattern=$2 - local negate=false - - [[ $pattern == !* ]] && negate=true && pattern="${pattern#!}" - - local regex="^" - local i c - for (( i=0; i<${#pattern}; i++ )); do - c="${pattern:$i:1}" - case "$c" in - "*") regex+=".*" ;; - "?") regex+="." ;; - ".") regex+="\." ;; - "/") regex+="/?" ;; - *) regex+="$c" ;; - esac - done - regex+="$" - - [[ $file =~ $regex ]] && result=true || result=false - - if [ "$negate" = "true" ]; then - [ "$result" = "false" ] - else - [ "$result" = "true" ] - fi -} - -main() { - local filters="$INPUT_FILTERS" - local changed_files - mapfile -t changed_files < <(get_changed_files) - - echo "📄 Found $((${#changed_files[@]})) changed files" - for file in "${changed_files[@]}"; do - [ -n "$file" ] && echo " $file" - done - - local current_group="" - local lines - mapfile -t lines <<< "$filters" - - declare -A group_match - - for line in "${lines[@]}"; do - [[ -z "$line" ]] && continue - - if [[ $line =~ ^[[:space:]]*([a-zA-Z0-9_-]+):[[:space:]]*$ ]]; then - current_group="${BASH_REMATCH[1]}" - group_match["$current_group"]=false - elif [[ $line =~ ^[[:space:]]*-[[:space:]]*[\'\"]?(.*[^\'\"])[\'\"]?[[:space:]]*$ ]]; then - local pattern="${BASH_REMATCH[1]}" - pattern="${pattern%\"}" && pattern="${pattern%\'}" - pattern="${pattern#\"}" && pattern="${pattern#\'}" - - for file in "${changed_files[@]}"; do - if [ -n "$file" ] && match_pattern "$file" "$pattern"; then - group_match["$current_group"]=true - echo "::debug::Match: '$file' ~ '$pattern' => $current_group=true" - fi - done - fi - done - - for group in "${!group_match[@]}"; do - echo "$group=${group_match[$group]}" >> $GITHUB_OUTPUT - echo "::debug::Output: $group=${group_match[$group]}" - done -} - -main "$@" diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 13c667125a..42c8abefc3 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -43,12 +43,6 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/paths-filter - id: filter - with: - filters: | - docs: - - '!**/*.md' license-header: name: License header runs-on: ubuntu-latest diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 26807948f3..2dca95b378 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -43,12 +43,6 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/paths-filter - id: filter - with: - filters: | - docs: - - '!**/*.md' license-header: name: License header runs-on: ubuntu-latest diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 71c7189736..d5f7ef750c 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -38,12 +38,6 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/paths-filter - id: filter - with: - filters: | - docs: - - '!**/*.md' license-header: name: License header runs-on: ubuntu-latest diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index f448fdc842..382f950d12 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -38,12 +38,6 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/paths-filter - id: filter - with: - filters: | - docs: - - '!**/*.md' build: name: Build runs-on: ${{ matrix.os }} diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 47c2be407a..8fbee135a4 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -43,12 +43,6 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/paths-filter - id: filter - with: - filters: | - docs: - - '!**/*.md' license-header: name: License header runs-on: ubuntu-latest From 4e0949adbb3801dc44ce08a94f849754d7f30712 Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 20:39:01 +0800 Subject: [PATCH 21/26] [Improve] paths-filter plugin improvement --- .github/workflows/backend.yml | 6 ++++++ .github/workflows/docs.yml | 6 ++++++ .github/workflows/e2e.yml | 6 ++++++ .github/workflows/unit-test.yml | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 42c8abefc3..543500d7aa 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -43,6 +43,12 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 + id: filter + with: + filters: | + not-ignore: + - '!**/*.md' license-header: name: License header runs-on: ubuntu-latest diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 2dca95b378..f64d7e7eef 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -43,6 +43,12 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 + id: filter + with: + filters: | + not-ignore: + - '**.md' license-header: name: License header runs-on: ubuntu-latest diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index d5f7ef750c..3da664d980 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -38,6 +38,12 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 + id: filter + with: + filters: | + not-ignore: + - '!**/*.md' license-header: name: License header runs-on: ubuntu-latest diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 8fbee135a4..ee604d4f0b 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -43,6 +43,12 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 + id: filter + with: + filters: | + not-ignore: + - '!**/*.md' license-header: name: License header runs-on: ubuntu-latest From 7e8fd81759f0684ac12b640d7eeed38c0223b0a7 Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 20:44:44 +0800 Subject: [PATCH 22/26] [Improve] paths-filter plugin improvement --- .github/workflows/frontend.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 382f950d12..b873d7a623 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -38,6 +38,12 @@ jobs: not-ignore: ${{ steps.filter.outputs.not-ignore }} steps: - uses: actions/checkout@v4 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 + id: filter + with: + filters: | + docs: + - '!**/*.md' build: name: Build runs-on: ${{ matrix.os }} From 74cd002c428ec3577f8aec334a9b69cb6dd0c389 Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 20:49:28 +0800 Subject: [PATCH 23/26] [Improve] import package improvement --- .../apache/streampark/console/system/authentication/JWTUtil.java | 1 - 1 file changed, 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index 68cef9c977..9748a9345c 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -33,7 +33,6 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.security.SecureRandom; import java.util.Base64; import java.util.Date; import java.util.regex.Pattern; From bfe59f11708cb1384adaed05a0a112ded99a52d3 Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 20:55:49 +0800 Subject: [PATCH 24/26] [Improve] .github/workflows/frontend.yml improvement --- .github/workflows/frontend.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index b873d7a623..ce01c69e52 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -42,7 +42,7 @@ jobs: id: filter with: filters: | - docs: + not-ignore: - '!**/*.md' build: name: Build From 31dec56e34bbee3e489535f18b0e6cac8472a92d Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 21:27:38 +0800 Subject: [PATCH 25/26] [Improve] JWTUtil minor improvement --- .../streampark/console/system/authentication/JWTUtil.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index 9748a9345c..0db7980ca2 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -33,6 +33,7 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; import java.util.Base64; import java.util.Date; import java.util.regex.Pattern; @@ -184,7 +185,7 @@ public static boolean verify(String token) { public static String encrypt(String content) throws Exception { // Generate a random IV byte[] iv = new byte[GCM_IV_LENGTH]; - SECURE_RANDOM.nextBytes(iv); + SecureRandom.getInstanceStrong().nextBytes(iv); SecretKeySpec keySpec = new SecretKeySpec(JWT_KEY, "AES"); From 5e0231eed51470a63aedc1dc78138bf5a7ee8981 Mon Sep 17 00:00:00 2001 From: benjobs Date: Sun, 3 Aug 2025 23:35:14 +0800 Subject: [PATCH 26/26] [Improve] JWT verify token bug fixed --- .../streampark/console/system/authentication/JWTUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java index 0db7980ca2..ac87684ae3 100644 --- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java +++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java @@ -165,7 +165,7 @@ public static boolean verify(String token) { // Decode the signing key using Base64 Algorithm algorithm = Algorithm.HMAC256(JWT_KEY); JWTVerifier verifier = JWT.require(algorithm).build(); - verifier.verify(decrypt(token)); + verifier.verify(token); return true; } catch (Exception e) { log.warn("Invalid JWT: {}", e.getMessage());