基于ProGuard-Maven-Plugin的自定义代码混淆插件

介绍了一种基于Maven的代码混淆插件,该插件不仅支持Jar包混淆,还支持War包混淆,有效防止代码被反编译,保护代码安全。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家可能都会碰到一些代码比较敏感的项目场景,这个时候代码被反编译看到就不好了,这个时候就需要代码混淆插件来对代码进行混淆了。

基于Maven的项目一般会去考虑使用proguard-maven-plugin,但是这个插件仅支持打Jar包不支持打War包。

于是我用空闲时间在proguard-maven-plugin的基础上修改了里面的一部分逻辑,可以在项目构建过的时候把代码混淆,支持打成jar包和war包。 

现在贴出来给大家看看。

项目地址
https://github.com/lovethegirl/code-hidding-plugin

修改部分
War包压缩解压的工具类

package com.github.wvengen.maven.proguard;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
 
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.jar.JarArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FileUtils;
 
/**
 * 处理WAR文件工具类。可压缩或解压缩WAR文件。
 * 
 * @author Xiong Shuhong(shelltea@gmail.com)
 */
public class WarUtils {
    public static void unzip(String warPath, String unzipPath) {
        File warFile = new File(warPath);
        try {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(
                warFile));
            ArchiveInputStream in = new ArchiveStreamFactory().createArchiveInputStream(
                ArchiveStreamFactory.JAR, bufferedInputStream);
 
            JarArchiveEntry entry = null;
            while ((entry = (JarArchiveEntry) in.getNextEntry()) != null) {
                File file = new File(unzipPath, entry.getName());
                if (file.exists()) {
                    file.delete();
                }
                if (entry.isDirectory()) {
                    file.mkdir();
                } else {
                    OutputStream out = FileUtils.openOutputStream(file);
                    IOUtils.copy(in, out);
                    out.close();
                }
            }
            in.close();
        } catch (FileNotFoundException e) {
            System.err.println("未找到war文件");
        } catch (ArchiveException e) {
            System.err.println("不支持的压缩格式");
        } catch (IOException e) {
            System.err.println("文件写入发生错误");
        }
    }
 
    public static void zip(String destFile, String zipDir) {
        File outFile = new File(destFile);
        try {
            outFile.createNewFile();
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                new FileOutputStream(outFile));
            ArchiveOutputStream out = new ArchiveStreamFactory().createArchiveOutputStream(
                ArchiveStreamFactory.JAR, bufferedOutputStream);
 
            if (zipDir.charAt(zipDir.length() - 1) != '/') {
                zipDir += '/';
            }
 
            Iterator<File> files = FileUtils.iterateFiles(new File(zipDir), null, true);
            while (files.hasNext()) {
                File file = files.next();
                ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(file, file.getPath().replace(
                    zipDir.replace("/", "\\"), ""));
                out.putArchiveEntry(zipArchiveEntry);
                IOUtils.copy(new FileInputStream(file), out);
                out.closeArchiveEntry();
            }
            out.finish();
            out.close();
        } catch (IOException e) {
            System.err.println("创建文件失败");
        } catch (ArchiveException e) {
            System.err.println("不支持的压缩格式");
        }
    }
}
修改ProGuardMojo.java中的代码,在打包的时候把混淆后的代码打进war包,具体可从Git上把项目down下来查看。
if (attach && !sameArtifact) {
            //操作war解压,等一系列操作
            String absolutePath = outJarFile.getAbsolutePath();
            getLog().info("---absolutePath--" + absolutePath);
            String unzipPath = outJarFile.getParent() + "/proguard-war";
            getLog().info("删除路径" + absolutePath);
            deleteDir(unzipPath);
            File unZipFile = new File(unzipPath);
            unZipFile.mkdir();
            String targetWar = mavenProject.getBuild().getDirectory() + "/"
                               + mavenProject.getBuild().getFinalName() + ".war";
            getLog().info(targetWar);
            WarUtils.unzip(targetWar, unzipPath);
            //删除路径"
            deleteDir(unzipPath + "/WEB-INF/classes");
            WarUtils.unzip(absolutePath, unzipPath + "/WEB-INF/classes");
            outJarFile.delete();
            WarUtils.zip(absolutePath, outJarFile.getParent() + "/proguard-war");
            getLog().info("---absolutePath--" + absolutePath);
            if (useArtifactClassifier()) {
                projectHelper.attachArtifact(mavenProject, attachArtifactType,
                    attachArtifactClassifier, outJarFile);
            } else {
                projectHelper.attachArtifact(mavenProject, attachArtifactType, null, outJarFile);
            }
        }
然后,运行maven install后,可以在仓库目录中看到打出来的混淆过的war包

使用方法

先进行Maven install

然后在需要混淆代码的工程中加入此插件的依赖

      <plugin>
                <groupId>com.jiujie</groupId>
                <artifactId>code-hidding-plugin</artifactId>
                <version>1.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>proguard</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <obfuscate>true</obfuscate>
                    <attach>true</attach>
                    <injar>classes</injar>
                    <attachArtifactClassifier>pg</attachArtifactClassifier>
                    attach 的作用是在 install 与 deploy 时将生成的 pg 文件也安装与部署
                    <proguardInclude>${basedir}/proguard.conf</proguardInclude>
                    <outjar>${project.build.finalName}-pg</outjar>
                    <libs>
                        <lib>${java.home}/lib/rt.jar</lib>
                        <lib>${java.home}/lib/jsse.jar</lib>
                    </libs>
                    <addMavenDescriptor>false</addMavenDescriptor>
                </configuration>
            </plugin>
在工程根目录下加入工程配置文件proguard.conf

# ----------------------------------  
#  通过指定数量的优化能执行  
#  -optimizationpasses n  
# ----------------------------------  
#-optimizationpasses 3  

# ----------------------------------  
#   混淆时不会产生形形色色的类名   
#   -dontusemixedcaseclassnames  
# ----------------------------------  
#-dontusemixedcaseclassnames
# ----------------------------------  
#      指定不去忽略非公共的库类  
#  -dontskipnonpubliclibraryclasses  
# ----------------------------------  

# ----------------------------------  
#       不预校验  
#    -dontpreverify  
# ----------------------------------  
# -dontpreverify  
#忽略所有告警
-ignorewarnings
#不做 shrink
-dontshrink
#不做 optimize
-dontoptimize


# ----------------------------------  
#      输出生成信息  
#       -verbose  
# ----------------------------------  
-verbose  

#混淆时应用侵入式重载   
#-overloadaggressively   

#优化时允许访问并修改有修饰符的类和类的成员   
#-allowaccessmodification  
#确定统一的混淆类的成员名称来增加混淆   


#这里添加你不需要混淆的类  
#-keep  class com.showjoy.common.cache.** {*;}   
-keepclasseswithmembers class com.showjoy.cart.service.** {  
    <fields>;  
}  
-keepclasseswithmembers class com.showjoy.cart.ui.cart.** {  
    <fields>;  
}  
-keepclassmembers class com.showjoy.cart.CartControllerHandler {  
    <fields>;  
}  
-keepclassmembers class com.showjoy.cart.CartExceptionHandler {  
    <fields>;  
}  
-keep class com.showjoy.cart.util.EncodeUtil {*;}   

#-keep public class * extends  javax.servlet.Servlet  


#-keepdirectories  **  
#-keepattributes **  
#-useuniqueclassmembernames  
#保持源码名与行号(异常时有明确的栈信息),注解(默认会过滤掉所有注解,会影响框架的注解)
-keepattributes SourceFile,LineNumberTable,*Annotation*
#保持包注解类
-keepattributes Signature

#-keepnames class * implements java.io.Serializable  
# ---------保护所有实体中的字段名称----------  
#-keepclassmembers class * implements java.io.Serializable {  
#    <fields>;  
#}  

# --------- 保护类中的所有方法名 ------------  
#-keepclassmembers class * {  
#    public <methods>;  
#}  
ProGuard说明与配置
官网:http://proguard.sourceforge.net/
ProGuard的使用是为了:

1.创建紧凑的代码文档是为了更快的网络传输,快速装载和更小的内存占用.
2.创建的程序和程序库很难使用反向工程.
3.所以它能删除来自源文件中的没有调用的代码
4.充分利用java6的快速加载的优点来提前检测和返回java6中存在的类文件.


参数:
-include {filename} 从给定的文件中读取配置参数
-basedirectory {directoryname} 指定基础目录为以后相对的档案名称
-injars {class_path} 指定要处理的应用程序jar,war,ear和目录
-outjars {class_path} 指定处理完后要输出的jar,war,ear和目录的名称
-libraryjars {classpath} 指定要处理的应用程序jar,war,ear和目录所需要的程序库文件
-dontskipnonpubliclibraryclasses 指定不去忽略非公共的库类。
-dontskipnonpubliclibraryclassmembers 指定不去忽略包可见的库类的成员。


保留选项
-keep {Modifier} {class_specification} 保护指定的类文件和类的成员
-keepclassmembers {modifier} {class_specification} 保护指定类的成员,如果此类受到保护他们会保护的更好
-keepclasseswithmembers {class_specification} 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。
-keepnames {class_specification} 保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)
-keepclassmembernames {class_specification} 保护指定的类的成员的名称(如果他们不会压缩步骤中删除)
-keepclasseswithmembernames {class_specification} 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)
-printseeds {filename} 列出类和类的成员-keep选项的清单,标准输出到给定的文件


压缩
-dontshrink 不压缩输入的类文件
-printusage {filename}
-whyareyoukeeping {class_specification}


优化
-dontoptimize 不优化输入的类文件
-assumenosideeffects {class_specification} 优化时假设指定的方法,没有任何副作用
-allowaccessmodification 优化时允许访问并修改有修饰符的类和类的成员

混淆
-dontobfuscate 不混淆输入的类文件
-printmapping {filename}
-applymapping {filename} 重用映射增加混淆
-obfuscationdictionary {filename} 使用给定文件中的关键字作为要混淆方法的名称
-overloadaggressively 混淆时应用侵入式重载
-useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆
-flattenpackagehierarchy {package_name} 重新包装所有重命名的包并放在给定的单一包中
-repackageclass {package_name} 重新包装所有重命名的类文件中放在给定的单一包中
-dontusemixedcaseclassnames 混淆时不会产生形形色色的类名
-keepattributes {attribute_name,...} 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.
-renamesourcefileattribute {string} 设置源文件中给定的字符串常量

因为我们开发的是webwork+spring+hibernate的架构的项目,所有需要很详细的配置。(经过n次失败后总结)


Example:
-injars <project>.jar
-outjars <project>_out.jar
-libraryjars <java.home>/lib/rt.jar
-libraryjars <project.home>/webroot/WEB-INF/lib/webwork.jar
.......

# 保留实现Action接口类中的公有的,友好的,私有的属性 和 公有的,友好的方法。其它的全部压缩,优化,混淆。
# 因为配置文件中的类名是一个完整的类名,如果经过处理后就有可能找不到这个类。
# 属性是jsp页面所需要的,如果经过处理jsp页面就无法得到action中的数据。
-keep public class * implements com.opensymphony.xwork.Action{
public protected private <fields>;
public protected <methods>;
}
# 保留实现了Serializable接口类中的公有的,友好的,私有的成员(属性和方法)
# 这个配置主要是对应实体类的配置。
-keep public class * implements java.io.Serializable{
public protected private *;
}
......
--------------------- 
作者:笔下生灰 
来源:优快云 
原文:https://blog.youkuaiyun.com/connect_me/article/details/51320913 
版权声明:本文为博主原创文章,转载请附上博文链接!

淘宝花钱买的最新版!需要的拿去! This asset obfuscates your code to make it harder for bad guys to reverse engineer your projects. Specifically designed for Unity, it seamlessly links in with its build process. The top priority of this package is to work straight out of the box with no extra steps required. While other obfuscators can stop a game from working, Beebyte's obfuscator looks for specific Unity related code that must be protected. The contents of your source files are unchanged, the obfuscation targets the compiled assembly. Features: - Supports IL2CPP - Supports Assembly Definition Files (Unity 2017.3+) - Removes Namespaces without any conflicts - Recognises Unity related code that must not be changed - Renames Classes (including MonoBehaviours) - Renames Methods - Renames Parameters - Renames Fields - Renames Properties - Renames Events - String literal obfuscation - Adds fake methods - Easy and extensive customisation using the Unity inspector window - Consistent name translations are possible across multiple builds and developers - Semantically secure cryptographic naming convention for renamed members The asset works for both Unity Free and Unity Pro version 4.2.0 onwards (including Unity 5 & 2017 & 2018). Build targets include Standalone, Android, iOS, WebGL, UWP. Other platforms are not guaranteed or supported but may become supported at a future date. IL2CPP builds are much harder to reverse engineer but strings and member information (class, method names etc) are visible in the global-metadata.dat file. Obfuscation will apply to this file adding further security. Why not complement your security with the Anti-Cheat Toolkit - a great third party asset. For more information about the Obfuscator, please see the FAQ
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值