Proguard混淆与Maven集成
1 prouard与maven集成
项目工程为Maven项目,在pom.xml配置文件中<plugins></plugins>中添加如下配置:
<plugin>
<groupId>com.pyx4me</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<includeDependency>true</includeDependency>
<proguardVersion>4.8</proguardVersion>
<obfuscate>true</obfuscate>
<maxMemory>1024m</maxMemory>
<proguardInclude>${basedir}/proguard.conf</proguardInclude>
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jce.jar</lib>
<lib>${java.home}/lib/jsse.jar</lib>
</libs>
<addMavenDescriptor>false</addMavenDescriptor>
</configuration>
<dependencies>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard</artifactId>
<version>4.8</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>
注意:如果本地服务器Nexus中无proguard-4.8.jar,请从网上下载该Jar包并上传到服务器Nexus.
2 Proguard配置
Proguard分为压缩、优化、混淆三部分:
2.1压缩
-dontshrink 不压缩输入的类文件
-printusage {filename}
-whyareyoukeeping {class_specification}
2.2.优化
-dontoptimize 不优化输入的类文件
-assumenosideeffects {class_specification} 优化时假设指定的方法,没有任何副作用
-allowaccessmodification 优化时允许访问并修改有修饰符的类和类的成员
2.3 混淆
2.3.1 混淆公共配置文件
#不混淆输入的类文件
-dontobfuscate
#打印映射
-printmapping{filename}
#重用映射增加混淆
-applymapping{filename}
#使用给定文件中的关键字作为要混淆方法的名称
-obfuscationdictionary {filename}
#混淆时应用侵入式重载
-overloadaggressively
#确定统一的混淆类的成员名称来增加混淆
-useuniqueclassmembernames
#重新包装所有重命名的包并放在给定的单一包中
-flattenpackagehierarchy{package_name}
#重新包装所有重命名的类文件中放在给定的单一包中
-repackageclass {package_name}
#混淆时不会产生形形色色的类名
-dontusemixedcaseclassnames
#保护给定的可选属性
-keepattributes{attribute_name,...}
##保持annotation注释属性,泛型中常用
-keepattributes *Annotation*
#解决泛型问题
-keepattributes Signature
#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
#不去忽略非公共的库类方法
-dontskipnonpubliclibraryclassmembers
#不预校验
-dontpreverify
#忽略告警,当确定该告警无影响的时候
-dontwarn net.landwind.hip.console.**
#工程中引入的jar包
-libraryjars jar包路径,例如:
D:\develop\apache-maven-3.1.1\repository8\org\springframework\spring-core\3.0.3.RELEASE\spring-core-3.0.3.RELEASE.jar
# 保留实现了Serializable接口类中的公有的,友好的,私有的成员(属性和方法)
# 这个配置主要是对应实体类的配置。
-keep publicclass * implements java.io.Serializable{
public protected private *;
}
# 枚举类型keep
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#保留方法名
-keepclassmembers class * {
public <methods>;
protected <methods>;
}
# 保留有该方法的类和该方法
-keepclasseswithmembers class XXX
-keepclasseswithmembers public class * {
public static voidmain(java.lang.String[]);
}
# 类似bean注入需要keep set 和 get 方法
-keepclassmembers public class * extendsXXX{
void set*(***);
*** get*();
}
2.3.2 Spring工程公共配置
-keep class javax.servlet.jsp.jstl.** {*; }
-dontwarn javax.servlet.jsp.jstl.*
-keep class * extendsjavax.servlet.http.HttpServlet
-keep class * implementsjavax.servlet.ServletContext { *; }
-keepclassmembers class * implementsjava.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-keep class org.dom4j.** { *; }
#-keep classjavax.jdo.datastore.DataStoreCache
-keep class org.apache.ws.commons.schema.** { *; }
-keep class javax.xml.** { *; }
-keep class org.apache.xml.serializer.** { *; }
-keep class org.apache.ws.** { *; }
-keep class com.ibm.wsdl.** { *; }
-keep class javax.wsdl.** { *; }
-keep class org.springframework.jndi.JndiPropertySource
-keep classorg.springframework.jndi.JndiLocatorDelegate { *; }
-keep classorg.springframework.context.** { *; }
-keep classorg.springframework.format.support.** { *; }
-keep classorg.springframework.ui.context.support.** { *; }
-keep classorg.springframework.validation.** { *; }
-keep classorg.springframework.http.** { *; }
-keep classorg.springframework.ui.velocity.** { *; }
-keep classorg.springframework.web.bind.** { *; }
-keep class org.springframework.web.context.**{ *; }
-keep classorg.springframework.web.context.ContextLoaderListener { *; }
-keep classorg.springframework.web.context.support.XmlWebApplicationContext { *; }
-keep class org.springframework.web.context.support.GenericWebApplicationContext{ *; }
-keep classorg.springframework.web.context.support.StaticWebApplicationContext { *; }
-keep classorg.springframework.web.context.support.AbstractRefreshableWebApplicationContext{ *; }
-keep classorg.springframework.web.context.WebApplicationContext { *; }
-keep classorg.springframework.web.filter.** { *; }
-keep classorg.springframework.web.servlet.i18n.**
-keep classorg.springframework.web.method.** { *; }
-keep class org.springframework.web.servlet.DispatcherServlet{ *; }
-keep classorg.springframework.web.servlet.config.**
-keep classorg.springframework.web.servlet.support.*
-keep classorg.springframework.web.servlet.theme.**
-keep classorg.springframework.web.servlet.view.*
-keep classorg.springframework.web.servlet.view.x**
-keep classorg.springframework.web.servlet.view.velocity.** { *; }
-keep classorg.springframework.web.util.** { *; }
-keep classorg.springframework.web.view.*
-keep class * implements org.springframework.web.context.ConfigurableWebApplicationContext{ *; }
-keep class * implementsorg.springframework.context.ApplicationListener { *; }
-keep class * extendsorg.springframework.web.context.support.XmlWebApplicationContext { *; }
-keep class * implementsorg.springframework.web.bind.support.WebArgumentResolver { *; }
-keep class org.springframework.core.MethodParameter {*;}
-keep class * extendsorg.springframework.web.servlet.DispatcherServlet { *; }
-keep classorg.springframework.beans.factory.** { *; }
-keep classorg.apache.velocity.runtime.directive.** { *; }
-keep classorg.apache.velocity.runtime.ParserPoolImpl
-keep class org.reflections.spring.**
-keep class * implementsjavax.servlet.FilterChain { *; }
-keepclassmembers class * {
@org.springframework.beans.factory.annotation.Autowired *;
@org.springframework.beans.factory.annotation.Qualifier *;
@org.springframework.beans.factory.annotation.Value *;
@org.springframework.beans.factory.annotation.Required *;
@org.springframework.context.annotation.Bean *;
@javax.annotation.PostConstruct *;
@javax.annotation.PreDestroy *;
@org.aspectj.lang.annotation.AfterReturning *;
@org.aspectj.lang.annotation.Pointcut *;
@org.aspectj.lang.annotation.AfterThrowing *;
@org.aspectj.lang.annotation.Around *;
@javax.jws.WebParam *;
@javax.jws.WebService *;
}
-keep@org.springframework.stereotype.Service class *
-keep@org.springframework.stereotype.Controller class *
-keep @org.springframework.stereotype.Componentclass *
-keep@org.springframework.stereotype.Repository class *
-keep@org.springframework.cache.annotation.EnableCaching class *
-keep@org.springframework.context.annotation.Configuration class *
-keep@org.springframework.web.bind.annotation.RequestMapping class *
-keep@org.springframework.web.bind.annotation.RequestMethod class *
-keep@org.springframework.web.bind.annotation.RequestParam class *
-keep@org.springframework.web.bind.annotation.ResponseBody class *
-keep @org.springframework.web.bind.annotation.PathVariableclass *
-keep @javax.jws.WebParam class *
-keep @javax.jws.WebService class *
-keep classorg.apache.commons.collections.ExtendedProperties { *; }
-keep class org.apache.commons.collections.map.LRUMap{ *; }
-keep classorg.apache.commons.lang.StringUtils { *; }
-keep classorg.apache.commons.lang.text.StrBuilder { *; }
-keep classorg.apache.commons.logging.Log { *; }
-keep classorg.apache.commons.lang.StringEscapeUtils { *; }
2.3.3 工程自定义配置及需要注意的地方
1.在配置文件中配置的实体类或者在JSP页面中用到的实体对象不要进行混淆;
2.在配置文件中配置了的类,类名不要混淆,其内部方法和变量可以进行混淆;
3.添加了配置文件的接口的实现类,接口可以进行完全混淆,只需要保留bean注入的set方法即可;
4.在配置文件中用到了类的初始化方法或者其他方法,在混淆时要保留,例如:
-keep class com.console.shiro.service.AuthServiceImpl {voidset*(***); java.lang.String loadFilterChainDefinitions();}
保留了bean注入的set方法和在配置文件里使用的loadFilterChainDefinitions()方法。
5.使用了Spring注解的接口,其类名和接口名和方法不能进行混淆;
6.Controller中使用参数注解的要带上名称,例如:
@PathVariable(value="path") String path则要带上(value="path")如果只使用注解不带上参数指定的名称,在混淆之后就会发生空指针异常;同样在@RequestBean("chMedicine")ChMedicinechMedicine,
@RequestParam("actionType")String actionType
实体bean注解和请求参数注解时要带上参数的名称;
7.一些辅助工具类的方法和类名也可以全部进行混淆,如果在配置文件中用到则不能混淆类名,各工程可以根据自身需求进行过滤混淆。
8.混淆整个类,类名除外:
-keep class com.console.core.GlobalContext
9.混淆整个类,set*()方法不进行混淆:
-keep class com.console.core.GenericServiceImpl {void set*(***);}
10.混淆类保留公共方法:
-keep class com.console.standards.dao.ChDiseaseMapper {public <methods>;}
11.保留类里面的某个方法:
-keep class com.console.shiro.service.AuthServiceImpl { java.lang.StringloadFilterChainDefinitions();}
12.混淆整个包,但是不混淆类名:
-keepclass com.console.standards.dao.impl.**
13.不混淆包下面的任何东西
-keep class com.console.standards.dao.impl.** {*;}
14.不混淆集成某个类的子类
-keep class * extendsjavax.servlet.http.HttpServlet
15.不混淆实现某个接口的子类
-keep class * implementsjavax.servlet.ServletContext { *; }
16.不混淆某个类的字段
-keep class com.console.core.web.**{<fields>;}
建议:如果要很好的将DAO和Service层进行混淆,尽量少使用注解。
此处只列出了部分常用混淆配置,其他配置根据各自工程需求进行添加。
3.工程搭建
3.1.Jar工程混淆
创建普通的Maven工程,及最终打包为Jar的工程,添加Proguard与maven集成的配置文件,配置见proguard与maven集成章节。
在pom.xml同级目录下添加proguard.conf配置文件,在此文件中添加对工程的混淆约束及文件过滤配置文件。
清理工程: mvn clean
打包命令: mvn package
部署到本地命令: mvn install
部署到服务器命令:mvn deploy
以上命令可以同时使用,
例如:mvn clean package install deploy则是将上面四步一次性进行处理。
3.2.WEB工程混淆
由于目前研究的Proguard技术暂时还未解决对WEB工程的混淆技术,因此将WEB工程拆分为两个工程再进行混淆。
3.2.1 分解工程(Jar工程)
将原始WEB工程console的Java代码及其配置文件全部拷贝到一个新的Jar工程console-lib(当然也是maven工程),文件包名、类名全部保持不变,POM.xml文件的配置与原始Console工程一样,只需修改工程名称为console-lib及打包的类型为jar,
<groupId>com.console</groupId>
<artifactId>console-lib</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>
<name>MavenWebapp Archetype</name>
<url>http://maven.apache.org</url>
修改<plugins></plugins>中的打包插件为
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>make-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<includes>
<include>**/console/**</include>
<include>**/**/*.xml</include>
<include>**/**/*.properties</include>
</includes>
<excludes>
<exclude>spring*.xml</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
再添加proguard与maven的集成配置,配置见proguard与maven集成章节。
在pom.xml同级目录下添加proguard.conf配置文件,在此文件中添加对工程的混淆约束及文件过滤配置文件。
打包命令同Jar工程混淆打包命令。
3.2.2 分解工程(WEB工程)
删掉java代码及配置文件,保留Spring加载的公共配置文件,具体配置根据各个工程而定。此时,工程中指剩下前端页面文件。
在web.xml中修改要初始化console-lib工程中的配置文件的,修改如下:
将<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/**/spring*.xml
</param-value>
</context-param>
修改为:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/**/spring*.xml,
classpath*:com/console/common/spring.xml,
classpath*:com/console/standards/spring.xml,
classpath*:com/console/sys/spring.xml,
classpath*:com/console/sys/person/spring.xml
</param-value>
</context-param>
在pom.xml文件中添加console-lib.jar的依赖:
<dependency>
<groupId>com.console</groupId>
<artifactId>console-lib</artifactId>
<version>1.0.0</version>
</dependency>
开发时需要将console和console-lib工程放在同一个工作空间,可以在console-lib工程中进行断点Debug;打包混淆好的console工程,必须先将console-lib工程部署到本地,或者部署到服务器,要保证本地和服务器的console-lib是混淆后的最新版本。
Console工程和console-lib工程在同一工作空间时,运行console WEB工程时无需再引入console-lib工程,只需将console-lib工程打开即可。只需要运行console WEB工程一个就行。
混淆之后的Java代码