Reputation: 2251
We developed a web application with play 2.2.3 and want to obfuscate it. I am trying to use sbt-proguard plugin. I put the line below to PROJECT_FOLDER/project/plugins.sbt file
addSbtPlugin("com.typesafe.sbt" % "sbt-proguard" % "0.2.2")
and put the lines below to PROJECT_FOLDER/build.sbt file
proguardSettings
ProguardKeys.options in Proguard ++= Seq("-dontnote", "-dontwarn", "-ignorewarnings")
ProguardKeys.options in Proguard += ProguardOptions.keepMain("Application")
inConfig(Proguard)(javaOptions in ProguardKeys.proguard := Seq("-Xmx2g"))
I am not sure proguard is working when I say dist on play console and on the plugin website they say call proguard:proguard. When I write proguard:proguard on play console, Play gives me error shown below
[info] Reading program jar [/Users/kamil/DEVELOPMENT/play-2.2.3/repository/local/net.sf.ehcache/ehcache-core/2.6.6/jars/ehcache-core.jar] (filtered)
[info] Reading program jar [/Users/kamil/DEVELOPMENT/play-2.2.3/repository/cache/org.json/json/jars/json-20140107.jar] (filtered)
[info] Reading library jar [/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/jce.jar]
[info] Reading library jar [/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/rt.jar]
[error] Error: The output jar is empty. Did you specify the proper '-keep' options?
[trace] Stack trace suppressed: run last proguard:proguard for the full output.
[error] (proguard:proguard) Proguard failed with exit code [1]
[error] Total time: 35 s, completed 10.Tem.2014 09:45:23
Is there anybody using this plugin with play framework succesfully?
Upvotes: 8
Views: 1910
Reputation: 617
Tom provided great answer. I may improve it slightly, and make modern for new versions of Play Framework and for Scala 3 (Scala 2 should work to).
-libraryjars target/universal/app-name-0.1.0-SNAPSHOT/lib
-keep @javax.inject.Singleton class * { <init>(...); }
-keep @javax.inject.Inject class * { <init>(...); }
name=your-app-name
version=0.1.0-SNAPSHOT
rm -rf share # remove docs
rm -rf bin # remove bin. You may run it via java -cp, see below
rm -rf logs # remove old logs
rm -f README.md # remove README
rm -f $name.$name-$version-sans-externalized.jar # remove old jar
zip -dq out.jar **.tasty # remove Scala 3 tasty files
zip -dq out.jar **.js # remove duplicated js files. You have them in assets jar
zip -dq out.jar **.html # remove duplicated html files. You have them in assets jar
java -Dconfig.file=conf/application.conf -Dlogback.configurationFile=conf/logback.xml -cp "conf/*:lib/*:out.jar" play.core.server.ProdServerStart # run
My whole proguard file:
-injars target/universal/my-app-0.1.0-SNAPSHOT/my-app.my-app-0.1.0-SNAPSHOT-sans-externalized.jar
-outjars target/universal/my-app-0.1.0-SNAPSHOT/out.jar
-libraryjars <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)
-libraryjars target/universal/my-app-0.1.0-SNAPSHOT/lib
-keep class !db.**,!log.**,!utils.**,** { *; }
-keep @javax.inject.Singleton class * { <init>(...); }
-keep @javax.inject.Inject class * { <init>(...); }
-dontwarn
-dontobfuscate
-dontoptimize
-dontnote
-ignorewarnings
You may notice -dontobfuscate
and -dontoptimize
options. You may try to avoid them, but it's hard to do due to Play Framework magic.
Note: out.jar name in proguard file should be the same as in java cp flag.
UPDATE: Actually, I found a way to obfuscate Scala Play framework code. You need to specify injars, outjars as I did it in the snippet above, and replace the other part on
-dontnote
-dontwarn
#-dontoptimize
-optimizations code/allocation/variable,code/removal/simple,code/removal/advanced,code/simplification/math,code/simplification/string,code/simplification/object,code/simplification/arithmetic,class/marking/final,method/inlining/tailrecursion
# Keep all annotations, including constructor annotations
-keepattributes *Annotation*,EnclosingMethod,InnerClasses,Signature
# Keep all constructors for all classes
-keepclassmembers class * {
public <init>(...);
}
# Allow obfuscation for specific package/classes
-keep class router.** { *; }
Upvotes: 1
Reputation: 1273
After burning a few days on trying to make sbt-proguard configured properly, I gave up, and just used proguard after building the project.
Instead of including the obfuscation as a build part, I opened the zip file generated by activator dist
, obfuscated the jar and returned it back into the lib folder with the same name. Here is how to do it:
Proguard can run on its own. You simply download the tar file from sourceforge and run the jar with a configuration file like:
java -jar /path/to/proguard/lib/proguard.jar @CONF_FILE
Now for the configuration file, You need to specify:
outjar - the path for the obfuscated jar (output). At the end of the process just copy this jar back to the lib directory and rename it to the name of the in jar.
keep - any package-name, class, method or field that needs to keep its name. Common things that you should keep in a webapp:
3.1. controller method names.
3.2. any class that is used by play and specified in the application.conf like ErrorHandler, ApplicationLoader
3.3. All router-generated classes
Libraries - include all libraries in the lib file except for your own jars.
So your conf.pro file should like something like this:
-injars /path/to/jar/project-version-sans-externalized.jar(!META-INF)
-outjars /path/to/obfuscated/jar.jar
-keepnames class com.example.ErrorHandler
-keepnames class com.example.ApplicationLoader
-keepnames class controllers.**
-keepclassmembernames class controllers.** {
<methods>;
}
-keeppackagenames controllers.**, router.**, views.**
-keep class router.** {*;}
-keepnames class router.** {*;}
-keepclassmembers class router.** {*;}
-keep class views.** {*;}
-keepnames class views.** {*;}
-keepclassmembers class views.** {*;}
-libraryjars /usr/lib/jvm/latest/jre/lib/rt.jar
-libraryjars /path/to/lib/library1.jar
-libraryjars /path/to/lib/library2.jar
After obfuscation is done and you copied the output jar back to its old dir and name, you can zip back your project and you've got an obfuscated play project!
EDIT:
I really recommend looking at the proguard manual. It has many examples for different project setups and frameworks.
Upvotes: 2