在平常開發中,可能會遇到要對系統中比較敏感的代碼進行保護,那麼下面就總結一下保護源碼的方法中最簡單的方式,即文件加密html
首先,加密和解密的大體思想是:加密無非就是對class文件進行異或一下,解密呢,那就是再對class文件異或回來便可。java
加密後的文件若是想要用到的話,就須要classLoader動態加載進來,具體實現請移步至:自定義ClassLoader動態加載Class文件tomcat
1 /** 2 * 加解密類 3 */ 4 public class EdCipher { 5 6 private String encryptFolder = "encrypt"; 7 8 /** 9 * 加密方法 10 * @param name 須要加密的文件名 11 */ 12 public void encryptClass(String name) { 13 String path = getFilePath(name); 14 // classFile爲待加密的class文件 15 File classFile = new File(path); 16 if (!classFile.exists()) { 17 // TODO 若是文件不存在,作相應的處理。通常狀況下都是拋出異常; 18 } else { 19 // folder 是準備在待加密的文件也就是classFIle的同級目錄下建立一個文件夾,裏面放着加密後的文件 20 File folder = new File(classFile.getParent() + File.separator + encryptFolder); 21 if (!folder.exists()) { 22 folder.mkdirs(); 23 } 24 } 25 // cipheredClass 爲加密後文件的全路徑文件名 26 String cipheredClass = classFile.getParent() + File.separator + encryptFolder + File.separator + classFile.getName(); 27 try ( 28 FileInputStream fileInputStream = new FileInputStream(classFile); 29 BufferedInputStream bis = new BufferedInputStream(fileInputStream); 30 FileOutputStream fileOutputStream = new FileOutputStream(cipheredClass); 31 BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream) 32 ) { 33 int data; 34 while ((data = bis.read()) != -1) { 35 bos.write(data ^ 0xFF); 36 } 37 bos.flush(); 38 } catch (IOException e) { 39 e.printStackTrace(); 40 } 41 42 // 如今將原來未加密的文件刪除 43 classFile.delete(); 44 45 //下面這一句在文件後面加了一個「en」,最後生成的文件就是xxx.classen,這樣作的目的是爲了在啓動服務器的時候 46 //tomcat會自動檢查classespath下的class文件,若是我不加上一個「en」,那麼改加密文件就會被tomcat掃描到。 47 //若是被掃描到了,可是它又是一個被加密後的文件,頭部信息被修改了,那麼tomcat就會報錯,啓動不起來。這算是一個小技巧。 48 File oldFile = new File(path + "en"); 49 if (oldFile.exists()) { 50 oldFile.delete(); 51 } 52 File cipheredFile = new File(cipheredClass); 53 cipheredFile.renameTo(oldFile); 54 cipheredFile.getParentFile().delete(); 55 } 56 57 /** 58 * 解密方法 59 * @param name 須要解密的文件名 60 */ 61 protected byte[] decryptClass(String name) { 62 String path; 63 if (!name.contains(".class")) { 64 path = getDefFilePath(name); 65 } else { 66 path = name; 67 } 68 File encryptedClassFile = new File(path); 69 if (!encryptedClassFile.exists()) { 70 System.out.println("decryptClass() File:" + path + " not found!"); 71 return null; 72 } 73 byte[] result = null; 74 BufferedInputStream bis = null; 75 ByteArrayOutputStream bos = null; 76 try { 77 bis = new BufferedInputStream(new FileInputStream(encryptedClassFile)); 78 bos = new ByteArrayOutputStream(); 79 int data; 80 while ((data = bis.read()) != -1) { 81 bos.write(data ^ 0xFF); 82 } 83 bos.flush(); 84 result = bos.toByteArray(); 85 } catch (Exception e) { 86 e.printStackTrace(); 87 } finally { 88 try { 89 if (bis != null) { 90 bis.close(); 91 } 92 if (bos != null) { 93 bos.close(); 94 } 95 } catch (IOException e) { 96 e.printStackTrace(); 97 } 98 } 99 return result; 100 } 101 102 //獲取加密前文件的絕對路徑 103 private String getFilePath(String name) { 104 String path; 105 String str = name.substring(name.lastIndexOf(".") + 1, name.length()) + ".class"; 106 path = EdCipher.class.getResource(str).toString(); 107 path = path.substring(path.indexOf("file:/") + "file:/".length(), path.length()); 108 if (System.getProperty("os.name").toUpperCase().contains("LINUX")) { 109 path = File.separator + path; 110 } 111 return path; 112 } 113 114 //獲取加密後文件的絕對路徑 115 private String getDefFilePath(String name) { 116 String path; 117 String str = name.substring(name.lastIndexOf(".") + 1, name.length()) + ".classen"; 118 path = EdCipher.class.getResource(str).toString(); 119 path = path.substring(path.indexOf("file:/") + "file:/".length(), path.length()); 120 return path; 121 } 122 123 // 測試 124 public static void main(String[] args) { 125 EdCipher edCipher = new EdCipher(); 126 edCipher.encryptClass(args[0]); 127 } 128 }
1 <!-- 加密 --> 2 <target name="encrypt"> 3 <java classname="EdCipher" failonerror="true"> 4 <classpath refid="classpath.run"/> 5 <arg line="須要加密的文件的包名+文件名"/> 6 </java> 7 </target>