I want to obfuscate my web application built as WAR archive, as this sensitive application in first time deployed outside our data center. I tried to use the Proguard GUI tool to obfuscate the input war, with all the service jar required for the UI application, with other external dependencies. Though the Proguard runs successfully with some warnings, ex., duplicate definition of library class [javax.servlet.UnavailableException], the output war contains no classes, but has lib with the library jars and web.xml files. Any steps I mess? Any right document on this? I would appreciate if anyone can provide the right document or steps to successfully obfuscate a WAR file with dependent project (a .jar file) and other external jar files (that needs no obfuscation).
you wouldn't obfuscate a war but rather the jars your using. What you can do here is setup your project so the project that makes up the war - configuration xml, WEB-INF content, resources and the web content and servlet definitions and put your java in a library project. Obfuscate the library project and use those obfuscated jars in your web project.
That's what I do, hope it helps.
Protector4j is the best solution to obfuscate the war file, due to graphic user interface its too easy to use and their eclipse plugin is also available.
You will download it from this link
https://doc.protector4j.com/protect-tomcat-web-app
I have done the same way. I used the below url for code obfuscation and i am successful.
http://bratonfire.blogspot.com/2012/01/war-file-obfuscation-using-proguard.html
I created a new folder and redirected output of classes to this folder. But the strange thing is that i am able to see the .java and .class files in the two locations. I am also worried about recreating a war file. can someone mention the clear and detailed steps.
Thanks,
Rahul
We also have the same issue and need to obfuscate all classes packaged in war file.Here is the approach that I followed.
Firstly we need to set order of plugins **(compiler, proguard, war)**declared in pom.xml file as below.
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.0.14</version>
<configuration>
</configuration>
<executions>
<execution>
<!-- Dont worry about compiler error. For first time, change this value to package so that plugin installs successfully. -->
<phase>process-classes</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<warName>mfs-transaction-management</warName>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
<!-- Exclude your default packages from war packaging. Do not include "**" in double quotes in actual code -->
<packagingExcludes>
WEB-INF/classes/com/package/mypackage1/"**",
WEB-INF/classes/com/package/mypackage2/"**",
</packagingExcludes>
<webResources>
<webResource>
<directory>${project.build.directory}/proguardClasses</directory>
<targetPath>WEB-INF/classes</targetPath>
</webResource>
</webResources>
</configuration>
</plugin>
</plugins>`
Then create a file proguard.conf under the root of your project at the same level where pom.xml is placed.
Add your own configuration regarding proguard in the file and the add below two lines in this file to tell input and output folder to proguard plugin.
You need to set paths according to your project structure in these lines
-injars 'C:\Users\Rajdeep\git\dfs-core\mfs-transaction-management\target\classes'
-outjars 'C:\Users\Rajdeep\git\dfs-core\mfs-transaction-management\target\proguardClasses'
Apart from this you need to install proguard-base manually in maven repository using mvn install command.
Provide your own groupid, artifact and version and made same changes to pom.
It is proguard.jar found under proguard6.0.3\lib folder when you download proguard manually.
I think everything will be ok and now when you run mvn clean package, your war file should included obfuscated class files.
Use Proguard GUI to obfuscate war files.
Once you run proguardgu.bat or proguardgui.sh file from bin folder of your proguard directory. You can select wars by clicking Input/output menu.
Related
I am new to maven. I have created a maven project which will be packaged to JAR. I did clean package then jar is created. When i extracted the same jar, i could not see any dependencies (jars) i added in pom.xml inside the packaged jar. If i give this jar to third party clients how will the code work without any dependent jars ? Please help me how maven manages the jars?
Thanks!
Maven handles dependencies based on how you configure the dependency plugin.
See this reference for a simple example of how to do this.
In this example, the following code configures where your dependencies will end up:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>log4j</includeGroupIds>
<outputDirectory>${project.build.directory}/dependency-jars/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Then this code sets up the classpath for your main jar, which will allow anyone running it to find these dependencies
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.mkyong.core.App</mainClass>
<classpathPrefix>dependency-jars/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
Your other option would be to create a single jar, with all dependencies included, by following this example here
You could distribute the jar and the POM file if you want to try and provide your users with the files in that manner, but they'd need to be able to access your Maven repository where those dependencies are kept.
Core maven doesn't handle this. Maven is a build tool, its work is to build an artifact (a jar in your case). Dependencies you define in your module's pom.xml file are needed to get the code compiled. You'll need maven plugins to do so.
Now, you're asking not about the build, but the distribution of your compiled binaries.
If I understand it should be a lot of jars (your and your dependencies). Alternatively you may distribute the code as a jar + dependencies inside.
Example:
A first case:
If your code resides in module A (say, the code is in packages org.a.*) and depends on some thirdparty (say, log4j, whose classes reside in org.apache.log4j) than you can expect that you jar will only contain the classes of module a and you expect that the log4j will be added by the user of your module automatically (The first case).
A second case:
module a.jar will contain both org.a.* and org.apache.log4j.* classes, everything in the same module.
In general the first approach is more "healthy" and in this case you shouldn't do anything in maven. Maybe your distribution tool/documentation should contain this information.
If someone uses the module a in his/her code like a thirdparty (if you develop a framework or something) and if his/her project is mavenized, than the fact you've defined a dependency on log4j will make the maven to download the log4j as well as your a.jar (In maven notation, this is called "transitive dependencies").
If you're interested in the second case (this can be relevant if you define some "client application", like "jndi client for some server" for example) you might want to take a look on Maven shade plugin
Beware this can lead to dependency hell (what if the application that uses your client also makes use of log4j? what if the log4j-s are of different version)/
Bottom line, you probably want the first approach, think twice before you decide the second approach :)
One more tip, if you just want to download all the dependencies of your module "a" you might want to use maven dependency plugin - type the following in the command prompt
mvn dependency:copy-dependencies
and you'll find all the dependencies in target/dependencies folder
Hope this helps and happy mavening
The simplest solution to the problem is to use the maven-assembly-plugin which can create such jar with dependencies like the following:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>distro-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Afterwards you can distribute the created jar xyz-1.0-jar-with-dependencies which contains the defined dependencies.
If you need more control on how the resulting artifact is created or if some files needed to be overwritten etc. you might take a deeper look into maven-shade-plugin
I'm developing a Java SE application with Netbeans IDE.
I added external jar files to the project.
After my project is compiled, these external jar files will be in the lib folder, next to the jar file.
I want to use jar in jar solution. So the external jar files are included in my project's runnable jar file.
Is any standard method to solve this problem? Or this is not a good solution?
Thank you!
I'm pretty sure that Java doesn't support embedded Jars. I'd recommend moving the lib out to the file system (so that it creates a sub folder ./lib within the same drctory as your executable Jar & see if that makes a difference.
If you really want to use embedded Jars, you could take a read of One-Jar
You should have a directory structure of
Example below
.\JarTest2.jar
.\lib\log4j-1.2.17.jar
You might wanna try One-JARâ„¢; and if your project is Maven-based:
<build>
<plugins>
<!-- other plugins omitted for brevity -->
<plugin>
<groupId>org.dstovall</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<configuration>
<attachToBuild>true</attachToBuild>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
MyProject > src
> target
> MyProject > classes (1)
> classes (2)
The actual newly compiled code is being put into 2, however the war file is getting created using 1. Thus my war file is not up to date at all.
What should I be doing ? Shown below snippet of my pom ... :
<build>
<finalName>MyProject</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>src\main\webapp\WEB-INF\web.xml</webXml>
<warName>MyProject</warName>
</configuration>
<version>2.1.1</version>
</plugin>
</plugins>
</build>
target/PROJ is nothing but exploded war.
try deleting target directory. Perform maven build from commandline. and check if all things are created as they are at this point. If so, then maven is behaving correctly as both of the places contains updated class files and that target/PROJ directory is exploded war directory. You can use path to that directory to setup a context in tomcat/web container.
I am a bit in doubt on what you are showing.
Normally in war project, the target should be something like
PROJ
+ target
+ classes
+ PROJ-version
+ WEB-INF
+ classes
I have never see a target/PROJ in Maven WAR project
If what I am showing is what you seen, then it is what Maven always do.
Source are compiled and put in classes.
During creation of WAR, different files, including the project's target/classes, will be copied to PROJ-version directory which form the structure of WAR, and it will be used to create the WAR file.
Therefore there should be no problem that Maven is using target/PROJ-version/WEB-INF/classes in creating the WAR, as it is getting copied from target/classes when you are building.
If it is not your case, probably I will suggest you share your POM. The directory you mentioned doesn't seems reasonable for a WAR project.
I'd like to add *.dlls as third party libs to my repository and during packaging process just pack them to *.jar, sign them and copy to some specific folder.
Signing and coping are well done and work correctly (as expected by using maven-dependency-plugin and maven-jarsigner-plugin). But I didn't find any method to automatically pack single dll to jar (without any sources like maven-assembly-plugin does).
Solution that I see by the time: add to my repository not a "pure" dll, but already packed to jar lib (packed by myself)... but it's not a good idea, I guess)
It sounds like you've successfully retrieved your .dll (with dependency plugin) and signed it (jarsigner plugin), and it's somewhere in your ${project.build.directory} (which defaults to target).
If that's correct, give this a try:
Define the packaging of your project as jar
Retrieve dlls
Make sure the jarsigner:sign goal is bound to the prepare-package phase. It binds to package by default and we need to ensure jarsigner:sign runs before jar:jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>sign</id>
<phase>prepare-package</phase> <!-- important -->
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
Configure the jar plugin to include the signed dll(s)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<!-- using this ID merges this config with default -->
<!-- So it should not be necessary to specify phase or goals -->
<!-- Change classes directory because it will look in target/classes
by default and that probably isn't where your dlls are. If
the dlls are in target then directoryContainingSignedDlls is
simply ${project.build.directory}. -->
<id>default-jar</id>
<configuration>
<classesDirectory>directoryContainingSignedDlls</classesDirectory>
<includes>
<include>**/*.dll</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Now, running mvn clean package should give you a jar containing your signed dlls.
If JACOB requires manifest config there are docs explaining how to do this.
Good luck!
I would recommend to pack your dll's as a zip archive via maven-assembly-plugin and let that module deploy the zip archive as attached to your usual pom. The packaging of that project should be pom instead of default.
I would be a little bit confused if i download a jar and find dll's inside it,
but if you prefer you could create jar via the maven-assembly-plugin or use the maven-jar-plugin.
I'm using proguard with a spring mvc application and maven.
My pom.xml's build section looks like:
<build>
<finalName>myapp</finalName>
<plugins>
<plugin>
<groupId>com.pyx4me</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<obfuscate>true</obfuscate>
<!--<options>-->
<!--<option>-keep public class</option>-->
<!--</options>-->
<injar>${project.build.finalName}</injar>
<injar>${project.build.finalName}</injar>
<inFilter>com.myapp.*</inFilter>
</configuration>
</plugin>
</plugins>
I also tried:
<injar>${project.build.finalName}.war</injar>
When I run:
mvn clean install
Build failure message:
[proguard] Reading program war [/Users/me/dev/git/myproject/myapp/target/myapp.war] (filtered)
[proguard] Error: The input doesn't contain any classes. Did you specify the proper '-injars' options?
ERROR] Failed to execute goal com.pyx4me:proguard-maven-plugin:2.0.4:proguard (default) on project myapp: Obfuscation failed (result=1) -> [Help 1]
It seems to have picked up my jar correctly as the messages before show:
[INFO] --- proguard-maven-plugin:2.0.4:proguard (default) # myapp ---
[INFO] execute ProGuard [-injars, '/Users/me/dev/gitserver/myproject/myapp/target/myapp.war'(!META-INF/maven/**,com.myapp.*), -outjars, '/Users/me/dev/git/myproject/myapp/target/myapp_pg.war', -libraryjars, ....
Also, what options do you suggest I use? This is a spring mvc so I have annotations like:
#Autowired
#Service
#Repository
#Controller
So any of those classes/fields should not be renamed I would imagine.
(My goal is just to make it a headache to someone who decompiles, such that they can't just decompile and use the code. Obfuscating will let them use it, but they won't be able to maintain the codebase unless they re-write it. I don't have any fancy algorithms so I have nothing really to hide in that respect.)
Update
Let me be clear here, my spring mvc using maven for some reason (I'm new to maven) when doing a mvn clean install produces both a myapp.war file and a exploded war myapp/ (this is what I want to deploy in production, not the myapp.war file)
My myapp folder has:
/target/myapp/
/target/myapp/meta-inf (empty folder)
/target/myapp/web-inf
/target/myapp/web-inf/classes (com.myapp. ...)
/target/myapp/web-inf/lib/
/target/myapp/web-inf/ web.xml, application.xml (for spring)
/target/myapp/web-inf/views/
So proguard should be obfuscating in the /target/myapp/web-inf/classes folder right?
How do I tell it to do so?
Update 2
I'm getting this now:
OK, I am not getting: failed to execute goal ...proguard .. Can't rename /Users/me/dev/git/project1/myapp/target/myapp/web-inf/classes (see my updates section for what I changed in my pom.xml)
I changed my pom.xml with:
<configuration>
<obfuscate>true</obfuscate>
<injar>${project.build.finalName}/WEB-INF/classes/</injar>
<inFilter>com/myapp/**</inFilter>
</configuration>
ProGuard filters work on file names, so
.....(!META-INF/maven/**,com.myapp.*)
probably won't match any class files. You probably want
.....(!META-INF/maven/**,com/myapp/**)
See ProGuard manual > Usage > File Filters
Can you post your entire pom?
Normally, Maven compiles to /target/classes (Even for WAR files) and the WAR plugin does the copy to web-inf/classes right before the package phase. You should not be manually compiling classes to web-inf/lib with Maven.
EDIT: OK this has take quite a bit of research, but I've found an answer for you. First, according to the ProGuard documentation, you should not have ANY classes in your war project:
Notably, class files that are in the WEB-INF/classes directory in a
war should be packaged in a jar and put in the WEB-INF/lib directory
You need to refactor your project so your web classes are built in a separate jar. Once you have built that jar project, you must add it as a dependency in your war project.
Once I created that setup, I was successfully able to build a war project with the following configuration:
<build>
<plugins>
<plugin>
<groupId>com.pyx4me</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<inFilter>com/example/**</inFilter>
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jsse.jar</lib>
</libs>
<options>
<option>-keep class com.example.echo.EchoServlet</option>
<option>-injar ${project.build.directory}/${project.build.finalName}.${project.packaging}</option>
<option>-outjar ${project.build.directory}/${project.build.finalName}-proguarded.${project.packaging}</option>
</options>
</configuration>
</plugin>
</plugins>
</build>
Note the "com.example.echo.EchoServlet". Since progaurd was going to change the name of my classes, I had to "keep" this servlet name so I could reference it in the WAR project's web.xml. If you use annotation based servlet configuration, I imagine this won't be necessary.