Obfuscate Spring Boot Applications with Proguard Maven Plugin

In Java, Spring Boot, Spring Framework
July 18, 2023

ProGuard

ProGuard is an open-sourced Java class file shrinker, optimizer, obfuscator, and preverifier. As a result, ProGuard processed applications and libraries are smaller, faster, and somewhat hardened against reverse engineering. (Proguard Manual)

ProGuard is an open-source and free tool that allows you to shrink, optimize and obfuscate Java-based codes. It detects unused classes, fields, methods, and attributes and deletes them at build time. Proguard is part of the Android SDK and is used when getting the release build.

What is Code Obfuscation?

This name is given to a “confusing” operation applied by changing the terms of classes and variables in a way that makes them difficult to read and understand. As a dictionary meaning, obfuscation means “the act or an instance of making something obscure, dark, or difficult to understand”. (source)

Why Do We Need This Process?

We use obfuscation to prevent the exposure of know-how or algorithms that we have developed specifically for our project. If our codes do not work on a server that belongs to us or if we are developing an Android application, we have to give the source codes of our application to the end user somehow. Therefore, we need this process in order to protect our labor. In this process, we can perform reduction and optimization operations in general, file size reduction, and a positive effect on application performance are provided.

How to Add Proguard to Spring Project?

Proguard can be used as a standalone, as well as with the help of an unofficial open-source project, as we will do with Maven. If you are using Gradle, you can add the officially available plugin to your dependencies.

Here’s the repository: https://github.com/ufukguler/book-portal/tree/reactive

1) First of all, you need to add the following build steps to the pom.xml file of our project:

<profiles>
    <profile>
        <id>proguard</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>com.github.wvengen</groupId>
                    <artifactId>proguard-maven-plugin</artifactId>
                    <version>2.5.3</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>proguard</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <injar>${project.build.finalName}.jar</injar>
                        <outjar>${project.build.finalName}.jar</outjar>
                        <obfuscate>true</obfuscate>
                        <proguardInclude>proguard.conf</proguardInclude>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                            <configuration>
                                <mainClass>com.bookportal.api.AppMediaApplication</mainClass>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

2) Then create a file named proguard.conf in the main directory of the project and paste it into it:

-dontshrink
-dontoptimize
-useuniqueclassmembernames
-adaptclassstrings
-dontnote
-ignorewarnings
-dontwarn

-keep class * extends org.springframework.boot.web.support.SpringBootServletInitializer
-keep class * extends org.springframework.boot.loader.**
-keepclasseswithmembers public class * { public static void main(java.lang.String[]);}
-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 *;
     @org.springframework.context.annotation.Primary *;
     @org.springframework.boot.context.properties.ConfigurationProperties *;
     @org.springframework.boot.context.properties.EnableConfigurationProperties *;

     ## thymeleaf (for html templates)
     *** get*();
     void set*(***);
}
-keep @org.springframework.cache.annotation.EnableCaching class *
-keep @org.springframework.context.annotation.Configuration class *
-keep @org.springframework.boot.context.properties.ConfigurationProperties class *
-keep @org.springframework.boot.autoconfigure.SpringBootApplication class *
-keep @org.springframework.stereotype.Repository class *
-allowaccessmodification
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod,RuntimeVisibleAnnotations
-keepdirectories org.springframework.boot.autoconfigure
-keepclassmembernames class * {
     java.lang.Class class$(java.lang.String);
     java.lang.Class class$(java.lang.String, boolean);
}
-keep class * implements java.io.Serializable
-keepclassmembers enum * { *; }

######
-keeppackagenames com.bookportal.api.controllers
-keepnames class com.bookportal.api.controllers

-keepclassmembernames class com.bookportal.api.auth.** { *; }
-keepclassmembernames class com.bookportal.api.configs.WebFluxSecurityConfig { *; } # spring security
-keepclassmembernames @interface * { *; }
-keepclassmembernames class com.bookportal.api.repository.** { *; }
-keepclassmembernames class com.bookportal.api.entity.** { *; }
-keepclassmembernames class com.bookportal.api.model.** { *; }

-keep class com.bookportal.api.response.CustomResponse { *; }
-keep class com.bookportal.model.** { *; } #DTO
-keep class com.bookportal.repository.** { *; } #Spring Data 
-keep class com.bookportal.entity.** { *; } #Database entities

-repackageclasses com.bookportal.api.proguard #move obfuscated class to
-classobfuscationdictionary proguard.txt #use these names while renaming classes
-obfuscationdictionary proguard.txt #use these names while renaming variables, methods etc.

You should change the MainClass and proguard.cfg parts specified in the pom.xml according to your application. In addition, you can add the build part under a new profile so it can only be useable with that profile without breaking your basic layout.

After these processes, let’s run the mvn clean package command and simply examine our jar file and then let us see the changes.

UserService before:

UserService after:

Package Structure before-after: