|
@@ -133,7 +133,7 @@ public class EncryptExecutor {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 要加密的lib包(若不指定,则加密筛选范围默认仅从项目代码本身进行筛选加密)。
|
|
* 要加密的lib包(若不指定,则加密筛选范围默认仅从项目代码本身进行筛选加密)。
|
|
|
- * <p>
|
|
|
|
|
|
|
+ * <pre>
|
|
|
* 提示: 不论项目里面的依赖的传递关系是怎样的,这里只需要指定需要加密的jar包全称即可。
|
|
* 提示: 不论项目里面的依赖的传递关系是怎样的,这里只需要指定需要加密的jar包全称即可。
|
|
|
* 说明:假设我们项目的pom依赖关系为: myProject -> a -> b -> c
|
|
* 说明:假设我们项目的pom依赖关系为: myProject -> a -> b -> c
|
|
|
* 即: 我们的项目myProject直接依赖的是a,我们在pom中主动指定依赖的也是a,没有主动指定需要依赖b和c,但是由于maven依赖传递的原因,
|
|
* 即: 我们的项目myProject直接依赖的是a,我们在pom中主动指定依赖的也是a,没有主动指定需要依赖b和c,但是由于maven依赖传递的原因,
|
|
@@ -147,26 +147,38 @@ public class EncryptExecutor {
|
|
|
* │ └─b.jar
|
|
* │ └─b.jar
|
|
|
* │ └─c.jar
|
|
* │ └─c.jar
|
|
|
* 这里,如果需要对a、b、c进行加密的话,只需要使includeLibSet值为["a.jar","b.jar","c.jar"]即可
|
|
* 这里,如果需要对a、b、c进行加密的话,只需要使includeLibSet值为["a.jar","b.jar","c.jar"]即可
|
|
|
|
|
+ * </pre>
|
|
|
*/
|
|
*/
|
|
|
private final Set<String> includeLibSet;
|
|
private final Set<String> includeLibSet;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 不需要加密的类的全类名前缀(也可以精确匹配)
|
|
* 不需要加密的类的全类名前缀(也可以精确匹配)
|
|
|
- * <p>
|
|
|
|
|
- * includePrefixSet匹配的类中再排除excludePrefixSet匹配的类,即为最终会被加密的类
|
|
|
|
|
|
|
+ * <pre>
|
|
|
|
|
+ * includePrefixSet匹配的类中再排除excludePrefixSet匹配的类,即为最终会被加密的类
|
|
|
|
|
+ * </pre>
|
|
|
*/
|
|
*/
|
|
|
private final Set<String> excludePrefixSet;
|
|
private final Set<String> excludePrefixSet;
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 已加密lib包所在根目录(,可为空,为空时自动根据当前是jar还是war,去包内对应找lib)
|
|
|
|
|
+ * <br />
|
|
|
|
|
+ * 特别注意:当指定此参数时,也会优先去jar/war内部找对应的lib包,找不到时,才会去此参数指定的根目录下找lib包
|
|
|
|
|
+ * <pre>
|
|
|
|
|
+ * 在一些外置lib的项目中,可能需要用到此参数;如果是内置lib,忽略此参数即可
|
|
|
|
|
+ * </pre>
|
|
|
|
|
+ */
|
|
|
|
|
+ private String alreadyProtectedRootDir;
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 已经被class-winter加密过了的lib的信息
|
|
* 已经被class-winter加密过了的lib的信息
|
|
|
- * <p>
|
|
|
|
|
|
|
+ * <pre>
|
|
|
* 每个pair对象的属性介绍:
|
|
* 每个pair对象的属性介绍:
|
|
|
* pair-左: lib包名,如: abc.jar
|
|
* pair-左: lib包名,如: abc.jar
|
|
|
* pair-右: 加密该lib时的密码
|
|
* pair-右: 加密该lib时的密码
|
|
|
- * <p>
|
|
|
|
|
* 想一想这种case:
|
|
* 想一想这种case:
|
|
|
* 第三方给你提供了一个被class-winter加密过的jar包,你把这个jar包依赖进你的项目your-project中,
|
|
* 第三方给你提供了一个被class-winter加密过的jar包,你把这个jar包依赖进你的项目your-project中,
|
|
|
* 你想正常的运行起来项目,那么你就需要用到这个属性了。
|
|
* 你想正常的运行起来项目,那么你就需要用到这个属性了。
|
|
|
|
|
+ * </pre>
|
|
|
*/
|
|
*/
|
|
|
private final Set<Pair<String, String>> alreadyProtectedLibSet;
|
|
private final Set<Pair<String, String>> alreadyProtectedLibSet;
|
|
|
|
|
|
|
@@ -207,7 +219,8 @@ public class EncryptExecutor {
|
|
|
String targetLibDir, String targetClassesDir, String password,
|
|
String targetLibDir, String targetClassesDir, String password,
|
|
|
Set<String> includeXmlPrefixSet, Set<String> excludeXmlPrefixSet, Set<String> toCleanXmlChildElementNameSet,
|
|
Set<String> includeXmlPrefixSet, Set<String> excludeXmlPrefixSet, Set<String> toCleanXmlChildElementNameSet,
|
|
|
Set<String> includePrefixSet, Set<String> excludePrefixSet, Set<String> includeLibSet,
|
|
Set<String> includePrefixSet, Set<String> excludePrefixSet, Set<String> includeLibSet,
|
|
|
- Set<Pair<String, String>> alreadyProtectedLibSet, String supportFile, Set<String> jvmArgCheckSet) {
|
|
|
|
|
|
|
+ String alreadyProtectedRootDir, Set<Pair<String, String>> alreadyProtectedLibSet,
|
|
|
|
|
+ String supportFile, Set<String> jvmArgCheckSet) {
|
|
|
this.originJarOrWar = originJarOrWar;
|
|
this.originJarOrWar = originJarOrWar;
|
|
|
this.originIsJar = originIsJar;
|
|
this.originIsJar = originIsJar;
|
|
|
this.finalName = finalName;
|
|
this.finalName = finalName;
|
|
@@ -221,6 +234,7 @@ public class EncryptExecutor {
|
|
|
this.includePrefixSet = includePrefixSet;
|
|
this.includePrefixSet = includePrefixSet;
|
|
|
this.excludePrefixSet = excludePrefixSet;
|
|
this.excludePrefixSet = excludePrefixSet;
|
|
|
this.includeLibSet = includeLibSet;
|
|
this.includeLibSet = includeLibSet;
|
|
|
|
|
+ this.alreadyProtectedRootDir = alreadyProtectedRootDir;
|
|
|
this.alreadyProtectedLibSet = alreadyProtectedLibSet;
|
|
this.alreadyProtectedLibSet = alreadyProtectedLibSet;
|
|
|
this.supportFile = supportFile;
|
|
this.supportFile = supportFile;
|
|
|
this.jvmArgCheckSet = jvmArgCheckSet;
|
|
this.jvmArgCheckSet = jvmArgCheckSet;
|
|
@@ -479,14 +493,26 @@ public class EncryptExecutor {
|
|
|
*/
|
|
*/
|
|
|
Map<String, String> allChecklistInfoMap = new HashMap<>(8);
|
|
Map<String, String> allChecklistInfoMap = new HashMap<>(8);
|
|
|
alreadyProtectedLibSet.forEach(pair -> {
|
|
alreadyProtectedLibSet.forEach(pair -> {
|
|
|
- String libJarName = pair.getLeft();
|
|
|
|
|
|
|
+ String libJarFilepath = pair.getLeft();
|
|
|
String password = pair.getRight();
|
|
String password = pair.getRight();
|
|
|
- File lib = new File(targetLibDir, libJarName);
|
|
|
|
|
|
|
+ // 定位lib
|
|
|
|
|
+ File lib = new File(targetLibDir, libJarFilepath);
|
|
|
if (!lib.exists()) {
|
|
if (!lib.exists()) {
|
|
|
- return;
|
|
|
|
|
|
|
+ if (StrUtil.isBlank(alreadyProtectedRootDir)) {
|
|
|
|
|
+ Logger.warn("do locate lib. " + libJarFilepath+ " non-exist. Under targetLibDir " + targetLibDir);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ lib = new File(alreadyProtectedRootDir, libJarFilepath);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (lib.exists()) {
|
|
|
|
|
+ Logger.debug("do locate lib. " + libJarFilepath+ " exist. Under alreadyProtectedRootDir " + alreadyProtectedRootDir);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Logger.warn("do locate lib. " + libJarFilepath+ " non-exist. Under alreadyProtectedRootDir " + alreadyProtectedRootDir);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
// 形如: META-INF/winter/abc-1.0.0_jar/
|
|
// 形如: META-INF/winter/abc-1.0.0_jar/
|
|
|
- String nonSuffixLibName = libJarName.substring(0, libJarName.length() - 4);
|
|
|
|
|
|
|
+ String libName = lib.getName();
|
|
|
|
|
+ String nonSuffixLibName = libName.substring(0, libName.length() - 4);
|
|
|
String dirRelativePathForLib = Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR + nonSuffixLibName + "_jar" + Constant.LINUX_FILE_SEPARATOR;
|
|
String dirRelativePathForLib = Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR + nonSuffixLibName + "_jar" + Constant.LINUX_FILE_SEPARATOR;
|
|
|
String dirAbsolutePathForLib = this.targetRootDir + File.separator + Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR + nonSuffixLibName + "_jar" + File.separator;
|
|
String dirAbsolutePathForLib = this.targetRootDir + File.separator + Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR + nonSuffixLibName + "_jar" + File.separator;
|
|
|
|
|
|
|
@@ -499,7 +525,7 @@ public class EncryptExecutor {
|
|
|
*/
|
|
*/
|
|
|
byte[] checklistOfAllLibsByte = IOUtil.readFileFromWorkbenchRoot(lib, Constant.CHECKLIST_OF_ALL_LIBS);
|
|
byte[] checklistOfAllLibsByte = IOUtil.readFileFromWorkbenchRoot(lib, Constant.CHECKLIST_OF_ALL_LIBS);
|
|
|
if (checklistOfAllLibsByte != null) {
|
|
if (checklistOfAllLibsByte != null) {
|
|
|
- throw new ClassWinterException(libJarName+"'s lib cannot be protected by class-winter.");
|
|
|
|
|
|
|
+ throw new ClassWinterException(libJarFilepath+"'s lib cannot be protected by class-winter.");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 清单文件
|
|
// 清单文件
|
|
@@ -527,7 +553,7 @@ public class EncryptExecutor {
|
|
|
byte[] libSealByte = IOUtil.readFileFromWorkbenchRoot(lib, Constant.SEAL_FILE);
|
|
byte[] libSealByte = IOUtil.readFileFromWorkbenchRoot(lib, Constant.SEAL_FILE);
|
|
|
if (libSealByte == null) {
|
|
if (libSealByte == null) {
|
|
|
// lib中没有印章文件
|
|
// lib中没有印章文件
|
|
|
- throw new ClassWinterException("Cannot find seal in lib [" + libJarName + "]. This lib is not "
|
|
|
|
|
|
|
+ throw new ClassWinterException("Cannot find seal in lib [" + libJarFilepath + "]. This lib is not "
|
|
|
+ "protected by class-winter.");
|
|
+ "protected by class-winter.");
|
|
|
} else {
|
|
} else {
|
|
|
IOUtil.writeContentToFile(new String(libSealByte, StandardCharsets.UTF_8), new File(dirAbsolutePathForLib,
|
|
IOUtil.writeContentToFile(new String(libSealByte, StandardCharsets.UTF_8), new File(dirAbsolutePathForLib,
|
|
@@ -537,16 +563,16 @@ public class EncryptExecutor {
|
|
|
// 密码
|
|
// 密码
|
|
|
// libUserIfInputPwd代表的意思是: 对lib进行混淆的时候,用户是否主动指定了密码
|
|
// libUserIfInputPwd代表的意思是: 对lib进行混淆的时候,用户是否主动指定了密码
|
|
|
boolean libUserIfInputPwd = Boolean.parseBoolean(new String(IOUtil.readFileFromWorkbenchRoot(lib, Constant.USER_IF_INPUT_PWD)));
|
|
boolean libUserIfInputPwd = Boolean.parseBoolean(new String(IOUtil.readFileFromWorkbenchRoot(lib, Constant.USER_IF_INPUT_PWD)));
|
|
|
- Logger.debug(EncryptExecutor.class, "libUserIfInputPwd info of lib [" + libJarName + "] -> " + libUserIfInputPwd);
|
|
|
|
|
|
|
+ Logger.debug(EncryptExecutor.class, "libUserIfInputPwd info of lib [" + libJarFilepath + "] -> " + libUserIfInputPwd);
|
|
|
if (libUserIfInputPwd && StrUtil.isBlank(password)) {
|
|
if (libUserIfInputPwd && StrUtil.isBlank(password)) {
|
|
|
// 加密lib时,用户主动指定了密码,那么这里password就不应该为空
|
|
// 加密lib时,用户主动指定了密码,那么这里password就不应该为空
|
|
|
- throw new ClassWinterException("Password is required to decrypt lib [" + libJarName + "]");
|
|
|
|
|
|
|
+ throw new ClassWinterException("Password is required to decrypt lib [" + libJarFilepath + "]");
|
|
|
}
|
|
}
|
|
|
if (StrUtil.isBlank(password)) {
|
|
if (StrUtil.isBlank(password)) {
|
|
|
byte[] libEncryptedPwdByte = IOUtil.readFileFromWorkbenchRoot(lib, Constant.PWD_WINTER);
|
|
byte[] libEncryptedPwdByte = IOUtil.readFileFromWorkbenchRoot(lib, Constant.PWD_WINTER);
|
|
|
if (libEncryptedPwdByte == null) {
|
|
if (libEncryptedPwdByte == null) {
|
|
|
// lib中没有密码文件,请指定此lib的密码
|
|
// lib中没有密码文件,请指定此lib的密码
|
|
|
- throw new ClassWinterException("Cannot find pwd from lib [" + libJarName + "]");
|
|
|
|
|
|
|
+ throw new ClassWinterException("Cannot find pwd from lib [" + libJarFilepath + "]");
|
|
|
} else {
|
|
} else {
|
|
|
// 因为写之前是加密写进去的,那么这里解密一下得到明文
|
|
// 因为写之前是加密写进去的,那么这里解密一下得到明文
|
|
|
// 存时,是加密存进去的; 这里读取时,(用lib的印章)解密一下
|
|
// 存时,是加密存进去的; 这里读取时,(用lib的印章)解密一下
|
|
@@ -970,6 +996,8 @@ public class EncryptExecutor {
|
|
|
private String toCleanXmlChildElementName;
|
|
private String toCleanXmlChildElementName;
|
|
|
|
|
|
|
|
private String includeLibs;
|
|
private String includeLibs;
|
|
|
|
|
+
|
|
|
|
|
+ private String alreadyProtectedRootDir;
|
|
|
|
|
|
|
|
private String alreadyProtectedLibs;
|
|
private String alreadyProtectedLibs;
|
|
|
|
|
|
|
@@ -1031,6 +1059,11 @@ public class EncryptExecutor {
|
|
|
return this;
|
|
return this;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public Builder alreadyProtectedRootDir(String alreadyProtectedRootDir) {
|
|
|
|
|
+ this.alreadyProtectedRootDir = alreadyProtectedRootDir;
|
|
|
|
|
+ return this;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public Builder supportFile(String supportFile) {
|
|
public Builder supportFile(String supportFile) {
|
|
|
this.supportFile = supportFile;
|
|
this.supportFile = supportFile;
|
|
|
return this;
|
|
return this;
|
|
@@ -1144,9 +1177,10 @@ public class EncryptExecutor {
|
|
|
Set<String> excludeXmlPrefixSet = StrUtil.strToSet(excludeXmlPrefix);
|
|
Set<String> excludeXmlPrefixSet = StrUtil.strToSet(excludeXmlPrefix);
|
|
|
toCleanXmlChildElementName = StrUtil.isBlank(toCleanXmlChildElementName) ? Constant.DEFAULT_XML_NODE_NAMES : toCleanXmlChildElementName;
|
|
toCleanXmlChildElementName = StrUtil.isBlank(toCleanXmlChildElementName) ? Constant.DEFAULT_XML_NODE_NAMES : toCleanXmlChildElementName;
|
|
|
Set<String> toCleanXmlChildElementNameSet = StrUtil.strToSet(toCleanXmlChildElementName);
|
|
Set<String> toCleanXmlChildElementNameSet = StrUtil.strToSet(toCleanXmlChildElementName);
|
|
|
|
|
+
|
|
|
return new EncryptExecutor(this.originJarOrWar, originIsJar, this.finalName, targetRootDir, targetLibDir, targetClassesDir,
|
|
return new EncryptExecutor(this.originJarOrWar, originIsJar, this.finalName, targetRootDir, targetLibDir, targetClassesDir,
|
|
|
password, includeXmlPrefixSet, excludeXmlPrefixSet, toCleanXmlChildElementNameSet, includePrefixSet,
|
|
password, includeXmlPrefixSet, excludeXmlPrefixSet, toCleanXmlChildElementNameSet, includePrefixSet,
|
|
|
- excludePrefixSet, includeLibSet, alreadyProtectedLibSet, this.supportFile, jvmArgCheckSet);
|
|
|
|
|
|
|
+ excludePrefixSet, includeLibSet, alreadyProtectedRootDir, alreadyProtectedLibSet, this.supportFile, jvmArgCheckSet);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|