Статьи

Запутывание Javascript с Maven и Google Closure

Оригинальное сообщение в блоге: http://eggsylife.co.uk/2011/04/18/obfuscating-javascript-with-maven-and-google-closure/

GitHub Repository — на примере проекта Maven

На момент написания статьи я не мог найти простой способ автоматизации обфускации Javascript при создании проекта Maven . Используя компилятор Googles Closure, я решил работать над своей концепцией. Это руководство показывает, как вы можете включить тот же процесс в свои проекты Maven.   

РЕДАКТИРОВАТЬ: wro4j это плагин, который использует компилятор Closure, однако он позволяет только обфускацию уровня SIMPLE_CUSTOMIZATIONS.  

Во-первых, вам нужно включить Exec-Maven . Этот плагин позволяет выполнять приложения Java во время процесса сборки. Включите этот плагин в ваш maven pom.xml следующим образом: 

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>uk.co.eggsylife.JavascriptObfuscator</mainClass>
<arguments>
<argument>${basedir}/src/main/webapp/scripts/raw.js</argument> <!-- Input file -->
<argument>${basedir}/src/main/webapp/scripts/raw.min.js</argument> <!-- Output file -->
</arguments>
</configuration>
</plugin>

Обратите внимание на конфигурацию плагина. Во-первых, мы нацелены на цель «Java». Я буду обсуждать это позже. Во-вторых, мы определяем основной класс . Это Java-приложение, которое будет запускать плагин. Наконец, у нас есть аргументы, это аргументы, которые будут переданы методу public static void main (String [] args) ‘. В приведенном выше примере мы передаем входной файл и местоположение / имя выходного файла. 

Теперь для класса ‘JavascriptObfuscator’. Этот класс взаимодействует с API-интерфейсом Closure Compiler, передавая исходный Javascript из входного файла — запрашивая обфусцированную версию из API, а затем сохраняя выходные данные в указанном выходном файле.  

package uk.co.eggsylife;
 
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
 
 
public class JavascriptObfuscator {
 
/**
* @param args
*/

public static void main(String[] args) {
 
System.out.println("Obfuscating Javascript");
 
if( args.length >= 2 ) {
 
int argumentCount = args.length;
String jsFile = args[0];
 
String outputFile = args[1];
 
String compilationLevel = "ADVANCED_OPTIMIZATIONS";
if(argumentCount == 3 ) {
compilationLevel = args[2];
}
 
 
String outputFormat = "text";
if(argumentCount == 4 ) {
outputFormat = args[3];
}
 
System.out.println("Processing ( " + jsFile + " )" );
System.out.println("Compilation Level ( " + compilationLevel + " )");
System.out.println("Output Format ( " + outputFormat + " )");
System.out.println("Saving to ( " + outputFile + " )");
 
StringBuffer contents = new StringBuffer();
BufferedReader reader = null;
 
try {
File file = new File(jsFile);
reader = new BufferedReader(new FileReader(file));
String text = null;
 
// Read the Javascript
while ((text = reader.readLine()) != null) {
contents.append(text).append(System.getProperty("line.separator"));
}
 
// Javascript Pre-Obfuscation
String jsCode = contents.toString();
 
ClosureCompiler compiler = new ClosureCompiler(outputFile, jsCode, compilationLevel, outputFormat);
compiler.processCompilation();
 
System.out.println("Obfuscation Finished");
 
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (reader != null) {
reader.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
 
}
else {
System.err.println("No (not enough) arguments passed to Obfuscation - requires JS file and Output directory");
}
}
}

Класс * должен * иметь как минимум два аргумента — входной и выходной файл — однако вы можете передать дополнительные аргументы, которые позволят вам настроить обфускацию компилятора Closure.

  • args [0] = входной файл (обязательно)
  • args [1] = выходной файл (обязательно)
  • args [2] = уровень компиляции (по умолчанию ADVANCED_OPTIMIZATIONS)
  • args [3] = выходной формат (тест по умолчанию)

Конечно, вы можете настроить этот класс так, чтобы он работал так, как вам нравится

Далее обратите внимание на использование класса ‘ClosureCompiler’, этот класс взаимодействует с API Closure

package uk.co.eggsylife;
 
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
 
public class ClosureCompiler {
 
private String outputFile = null;
private String jsCode = null;
private String compilationLevel = null;
private String outputFormat = null;
 
public ClosureCompiler(String outputFile, String jsCode, String compilationlevel, String outputFormat) {
this.outputFile = outputFile;
this.jsCode = jsCode;
this.compilationLevel = compilationlevel;
this.outputFormat = outputFormat;
}
 
public void processCompilation() {
try {
String obfuscatedCode = sendForCompilation();
saveObfuscatedCodeToFile(outputFile, obfuscatedCode);
}
catch (Exception e) {
System.err.println("Exception when obfuscating code: " + e.getMessage());
}
}
 
private String sendForCompilation() throws Exception {
URL url = new URL("http://closure-compiler.appspot.com/compile");
 
String data = URLEncoder.encode("js_code", "UTF-8") + "=" + URLEncoder.encode(jsCode, "UTF-8");
data += "&" + URLEncoder.encode("compilation_level", "UTF-8") + "=" + URLEncoder.encode(compilationLevel, "UTF-8");
data += "&" + URLEncoder.encode("output_format", "UTF-8") + "=" + URLEncoder.encode(outputFormat, "UTF-8");
data += "&" + URLEncoder.encode("output_info", "UTF-8") + "=" + URLEncoder.encode("compiled_code", "UTF-8");
 
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
 
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String codeLine;
 
StringBuffer obfuscatedCodeLine = new StringBuffer();
while ((codeLine = rd.readLine()) != null) {
obfuscatedCodeLine.append(codeLine).append(System.getProperty("line.separator"));
}
wr.close();
rd.close();
 
return obfuscatedCodeLine.toString();
}
 
private void saveObfuscatedCodeToFile(String outputdirectory, String javascriptCode) throws Exception{
FileWriter fstream = new FileWriter(outputdirectory);
BufferedWriter out = new BufferedWriter(fstream);
out.write(javascriptCode);
//Close the output stream
out.close();
}
 
}

Извлекает запутанный результат и сохраняет его в указанном выходном файле.

Это почти завершает блог, последнее, что нужно показать, как это будет вызывать ваш. Это просто, как:

mvn exec:java

Конечно, вы можете настроить цель плагина так, чтобы он запутывал, когда вам это нужно.

Я также приветствовал бы любые комментарии или дальнейшие настройки на этом