javaee加密部署项目通过tomcat使用自定义的classload解密
2017-06-16 13:39
405 查看
参考文章:http://blog.itpub.net/29754888/viewspace-1220306/
如上述文章所说,继承tomcat的WebappClassLoader自定义自己的classload,并不适用于spring。
原因是spring加载类是用另外的方式来加载。
意思应该是是需要封装的jar代码中不能有spring的注解(依赖注入、控制器声明等等)
原理:
通过加密java代码的class文件,实现对源代码的保护,并通过自定义的classload文件来解密class文件,把类加载到项目中
自定义自己的classload,并重写findClass方法。类加载器通过调用findClass方法,寻找并加载类文件。
通过重写findClass方法,可以把预先加密好的class文件,解密后再加载到项目中
package generator;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import org.apache.catalina.loader.WebappClassLoader;
/**
* 自定义的classloader 可以解密文件并加载
*
* @author uikoo9
*/
public class UClassLoader extends WebappClassLoader {
/**
* 算法
*/
private String algorithmStr="AES/ECB/PKCS5Padding";
/**
* key
*/
private String keyStr="abcdefg123456789";
/**
* 默认构造器
*
* @throws Exception
*/
public UClassLoader() {
super();
}
/**
* 默认构造器
*
* @param parent
* @throws Exception
*/
public UClassLoader(ClassLoader parent) {
super(parent);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.catalina.loader.WebappClassLoader#findClass(java.lang.String)
*/
public Class findClass(String name) throws ClassNotFoundException {
if (name.contains("com.A")
|| name.contains("com.B")
|| name.contains("com.C")) {
return findClassEncrypt(name);
} else {
return super.findClass(name);
}
}
/**
* 查找class
*
* @param name
* @return
* @throws ClassNotFoundException
*/
private Class findClassEncrypt(String name) throws ClassNotFoundException {
byte[] classBytes = null;
try {
classBytes = loadClassBytesEncrypt(name);
} catch (Exception e) {
e.printStackTrace();
}
Class cl = defineClass(name, classBytes, 0, classBytes.length);
if (cl == null) {
System.out.println("找不到该类:" + name);
throw new ClassNotFoundException(name);
}
return cl;
}
/**
* 加载加密后的class字节流
*
* @param name
* @return
* @throws Exception
*/
private byte[] loadClassBytesEncrypt(String name) throws Exception {
// 获取当前文件路径
// File directory = new File("");
// String parentPath = directory.getAbsolutePath()+File.separator;
String parentPath = "F:\\";
List<String> basepath = new ArrayList<String>();
basepath.add(parentPath + "A\\");// 项目物理地址
basepath.add(parentPath + "B\\");// 项目物理地址
basepath.add(parentPath + "C\\");// 项目物理地址
String cname = null;
File file = null;
for (String path : basepath) {
cname = path + name.replace('.', '\\') + ".cls";
file = new File(cname);
if (file.exists()) {
break;
}
}
if (file != null) {
if (!file.exists()) {
throw new Exception("File Not found:" + cname);
}
}
FileInputStream in = new FileInputStream(cname);
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] buf = new byte[1024 * 100];// 100KB
int len = 0;
while ((len = in.read(buf)) != -1) {
buffer.write(buf, 0, len);
}
in.close();
return decrypt(parseHexStr2Byte(new String(buffer.toByteArray())));
} finally {
in.close();
}
}
/**
* 解密
*
* @param content
* @return
*/
private byte[] decrypt(byte[] content) {
try {
byte[] keyBytes = this.keyStr.getBytes("utf-8");
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance(this.algorithmStr);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] result = cipher.doFinal(content);
return result;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* 十六进制字符串转字节
*
* @param hexStr
* @return
*/
private byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
}在tomcat的content.xml文件中,配置自定义的classload为tomcat默认的classload
在<Content>中添加如下代码
<Loader loaderClass="generator.UClassLoader" delegate="true"></Loader>指定环境上下文类加载为自定义的classload
注意:自定义的classload放在tomcat的lib下,并且文件夹层级结构需要跟包名一致generator/UClassLoader.class
大概步骤如下
1、对需要加密的class进行算法加密,本人是用AES加密
2、把加密后的class文件放到固定的地方,把项目中的对应class删除
3、修改context.xml的指定上下文类加载器为自定义加载器
4、启动tomcat
另外:如果不想自定义tomcat的classload,也可以自定义classload继承URLClassLoader
代码方式类似,也是通过重写findClass方法。编写好自定义classload后,在项目中实例化该类。
package classload;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class MyClassLoader extends URLClassLoader {
/**
* 算法
*/
private String algorithmStr="AES/ECB/PKCS5Padding";
/**
* key
*/
private String keyStr="abcdefg123456789";
public MyClassLoader(URL[] urls){
super(urls);
}
public MyClassLoader(URL[] urls, ClassLoader parent){
super(urls,parent);
}
public static void main(String[] args) throws MalformedURLException {
URL url = new File("a.jar").toURI().toURL();
MyClassLoader classLoader = new MyClassLoader(new URL[]{url},Thread.currentThread().getContextClassLoader());
//设置自定义classload为环境上下文类加载器
Thread.currentThread().setContextClassLoader(classLoader);
}
public Class findClass(String name) throws ClassNotFoundException {
if (name.contains("com.A")
|| name.contains("com.B")
|| name.contains("com.C")) {
return findClassEncrypt(name);
} else {
return super.findClass(name);
}
}
/**
* 查找class
*
* @param name
* @return
* @throws ClassNotFoundException
*/
private Class findClassEncrypt(String name) throws ClassNotFoundException {
byte[] classBytes = null;
try {
classBytes = loadClassBytesEncrypt(name);
} catch (Exception e) {
e.printStackTrace();
}
Class cl = defineClass(name, classBytes, 0, classBytes.length);
if (cl == null) {
System.out.println("找不到该类:" + name);
throw new ClassNotFoundException(name);
}
return cl;
}
/**
* 加载加密后的class字节流
*
* @param name
* @return
* @throws Exception
*/
private byte[] loadClassBytesEncrypt(String name) throws Exception {
// 获取当前文件路径
// File directory = new File("");
// String parentPath = directory.getAbsolutePath()+File.separator;
String parentPath = "F:\\";
List<String> basepath = new ArrayList<String>();
basepath.add(parentPath + "A\\");// 项目物理地址
basepath.add(parentPath + "B\\");// 项目物理地址
basepath.add(parentPath + "C\\");// 项目物理地址
String cname = null;
File file = null;
for (String path : basepath) {
cname = path + name.replace('.', '\\') + ".cls";
file = new File(cname);
if (file.exists()) {
break;
}
}
if (file != null) {
if (!file.exists()) {
throw new Exception("File Not found:" + cname);
}
}
FileInputStream in = new FileInputStream(cname);
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] buf = new byte[1024 * 100];// 100KB
int len = 0;
while ((len = in.read(buf)) != -1) {
buffer.write(buf, 0, len);
}
in.close();
return decrypt(parseHexStr2Byte(new String(buffer.toByteArray())));
} finally {
in.close();
}
}
/**
* 解密
*
* @param content
* @return
*/
private byte[] decrypt(byte[] content) {
try {
byte[] keyBytes = this.keyStr.getBytes("utf-8");
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance(this.algorithmStr);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] result = cipher.doFinal(content);
return result;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* 十六进制字符串转字节
*
* @param hexStr
* @return
*/
private byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
}
项目中加载该类
URL url = new File("a.jar").toURI().toURL();
MyClassLoader classLoader = new MyClassLoader(new URL[]{url},Thread.currentThread().getContextClassLoader());
//设置自定义classload为环境上下文类加载器
Thread.currentThread().setContextClassLoader(classLoader);
构造函数必须传URL对象参数进去,所以要随便指定一个jar。
如上述文章所说,继承tomcat的WebappClassLoader自定义自己的classload,并不适用于spring。
原因是spring加载类是用另外的方式来加载。
意思应该是是需要封装的jar代码中不能有spring的注解(依赖注入、控制器声明等等)
原理:
通过加密java代码的class文件,实现对源代码的保护,并通过自定义的classload文件来解密class文件,把类加载到项目中
自定义自己的classload,并重写findClass方法。类加载器通过调用findClass方法,寻找并加载类文件。
通过重写findClass方法,可以把预先加密好的class文件,解密后再加载到项目中
package generator;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import org.apache.catalina.loader.WebappClassLoader;
/**
* 自定义的classloader 可以解密文件并加载
*
* @author uikoo9
*/
public class UClassLoader extends WebappClassLoader {
/**
* 算法
*/
private String algorithmStr="AES/ECB/PKCS5Padding";
/**
* key
*/
private String keyStr="abcdefg123456789";
/**
* 默认构造器
*
* @throws Exception
*/
public UClassLoader() {
super();
}
/**
* 默认构造器
*
* @param parent
* @throws Exception
*/
public UClassLoader(ClassLoader parent) {
super(parent);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.catalina.loader.WebappClassLoader#findClass(java.lang.String)
*/
public Class findClass(String name) throws ClassNotFoundException {
if (name.contains("com.A")
|| name.contains("com.B")
|| name.contains("com.C")) {
return findClassEncrypt(name);
} else {
return super.findClass(name);
}
}
/**
* 查找class
*
* @param name
* @return
* @throws ClassNotFoundException
*/
private Class findClassEncrypt(String name) throws ClassNotFoundException {
byte[] classBytes = null;
try {
classBytes = loadClassBytesEncrypt(name);
} catch (Exception e) {
e.printStackTrace();
}
Class cl = defineClass(name, classBytes, 0, classBytes.length);
if (cl == null) {
System.out.println("找不到该类:" + name);
throw new ClassNotFoundException(name);
}
return cl;
}
/**
* 加载加密后的class字节流
*
* @param name
* @return
* @throws Exception
*/
private byte[] loadClassBytesEncrypt(String name) throws Exception {
// 获取当前文件路径
// File directory = new File("");
// String parentPath = directory.getAbsolutePath()+File.separator;
String parentPath = "F:\\";
List<String> basepath = new ArrayList<String>();
basepath.add(parentPath + "A\\");// 项目物理地址
basepath.add(parentPath + "B\\");// 项目物理地址
basepath.add(parentPath + "C\\");// 项目物理地址
String cname = null;
File file = null;
for (String path : basepath) {
cname = path + name.replace('.', '\\') + ".cls";
file = new File(cname);
if (file.exists()) {
break;
}
}
if (file != null) {
if (!file.exists()) {
throw new Exception("File Not found:" + cname);
}
}
FileInputStream in = new FileInputStream(cname);
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] buf = new byte[1024 * 100];// 100KB
int len = 0;
while ((len = in.read(buf)) != -1) {
buffer.write(buf, 0, len);
}
in.close();
return decrypt(parseHexStr2Byte(new String(buffer.toByteArray())));
} finally {
in.close();
}
}
/**
* 解密
*
* @param content
* @return
*/
private byte[] decrypt(byte[] content) {
try {
byte[] keyBytes = this.keyStr.getBytes("utf-8");
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance(this.algorithmStr);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] result = cipher.doFinal(content);
return result;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* 十六进制字符串转字节
*
* @param hexStr
* @return
*/
private byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
}在tomcat的content.xml文件中,配置自定义的classload为tomcat默认的classload
在<Content>中添加如下代码
<Loader loaderClass="generator.UClassLoader" delegate="true"></Loader>指定环境上下文类加载为自定义的classload
注意:自定义的classload放在tomcat的lib下,并且文件夹层级结构需要跟包名一致generator/UClassLoader.class
大概步骤如下
1、对需要加密的class进行算法加密,本人是用AES加密
2、把加密后的class文件放到固定的地方,把项目中的对应class删除
3、修改context.xml的指定上下文类加载器为自定义加载器
4、启动tomcat
另外:如果不想自定义tomcat的classload,也可以自定义classload继承URLClassLoader
代码方式类似,也是通过重写findClass方法。编写好自定义classload后,在项目中实例化该类。
package classload;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class MyClassLoader extends URLClassLoader {
/**
* 算法
*/
private String algorithmStr="AES/ECB/PKCS5Padding";
/**
* key
*/
private String keyStr="abcdefg123456789";
public MyClassLoader(URL[] urls){
super(urls);
}
public MyClassLoader(URL[] urls, ClassLoader parent){
super(urls,parent);
}
public static void main(String[] args) throws MalformedURLException {
URL url = new File("a.jar").toURI().toURL();
MyClassLoader classLoader = new MyClassLoader(new URL[]{url},Thread.currentThread().getContextClassLoader());
//设置自定义classload为环境上下文类加载器
Thread.currentThread().setContextClassLoader(classLoader);
}
public Class findClass(String name) throws ClassNotFoundException {
if (name.contains("com.A")
|| name.contains("com.B")
|| name.contains("com.C")) {
return findClassEncrypt(name);
} else {
return super.findClass(name);
}
}
/**
* 查找class
*
* @param name
* @return
* @throws ClassNotFoundException
*/
private Class findClassEncrypt(String name) throws ClassNotFoundException {
byte[] classBytes = null;
try {
classBytes = loadClassBytesEncrypt(name);
} catch (Exception e) {
e.printStackTrace();
}
Class cl = defineClass(name, classBytes, 0, classBytes.length);
if (cl == null) {
System.out.println("找不到该类:" + name);
throw new ClassNotFoundException(name);
}
return cl;
}
/**
* 加载加密后的class字节流
*
* @param name
* @return
* @throws Exception
*/
private byte[] loadClassBytesEncrypt(String name) throws Exception {
// 获取当前文件路径
// File directory = new File("");
// String parentPath = directory.getAbsolutePath()+File.separator;
String parentPath = "F:\\";
List<String> basepath = new ArrayList<String>();
basepath.add(parentPath + "A\\");// 项目物理地址
basepath.add(parentPath + "B\\");// 项目物理地址
basepath.add(parentPath + "C\\");// 项目物理地址
String cname = null;
File file = null;
for (String path : basepath) {
cname = path + name.replace('.', '\\') + ".cls";
file = new File(cname);
if (file.exists()) {
break;
}
}
if (file != null) {
if (!file.exists()) {
throw new Exception("File Not found:" + cname);
}
}
FileInputStream in = new FileInputStream(cname);
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] buf = new byte[1024 * 100];// 100KB
int len = 0;
while ((len = in.read(buf)) != -1) {
buffer.write(buf, 0, len);
}
in.close();
return decrypt(parseHexStr2Byte(new String(buffer.toByteArray())));
} finally {
in.close();
}
}
/**
* 解密
*
* @param content
* @return
*/
private byte[] decrypt(byte[] content) {
try {
byte[] keyBytes = this.keyStr.getBytes("utf-8");
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance(this.algorithmStr);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] result = cipher.doFinal(content);
return result;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* 十六进制字符串转字节
*
* @param hexStr
* @return
*/
private byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
}
项目中加载该类
URL url = new File("a.jar").toURI().toURL();
MyClassLoader classLoader = new MyClassLoader(new URL[]{url},Thread.currentThread().getContextClassLoader());
//设置自定义classload为环境上下文类加载器
Thread.currentThread().setContextClassLoader(classLoader);
构造函数必须传URL对象参数进去,所以要随便指定一个jar。
相关文章推荐
- javaee加密部署,tomcat使用自己的classloader解密【正解】
- javaee加密部署,tomcat使用自己的classloader解密【正解】
- javaee加密部署,tomcat使用自己的classloader解密
- javaee加密部署,tomcat使用自己的classloader解密
- javaee加密,tomcat使用自己的classloader解密
- Java加密部署,使用自定义的classloader解密的方法实例
- 使用maven的tomcat:run进行web项目热部署(通过Maven的Tomcat插件运行Web工程,在pom中添加tomcat插件,使项目能在eclipse中跑起来,但如果部署需安tomcat)
- 使用weinre在PC端同步远程调试移动端页面(在xampp上部署项目到Tomcat,并通过外网访问(图解). )
- 使用maven部署项目到tomcat 7
- 在Eclipse中使用Tomcat部署Web项目
- 关于WEB项目部署时TOMCAT和JDK的使用的方法
- tomcat部署多个项目,通过域名解析访问,不同的网站
- MyEclilpse 使用 SVN 控制版本 使用 tomcat6.0 服务器部署web项目
- 使用Ant构建web项目 从编译到测试 生成测试报告 打包 邮件发送 远程下载tomcat 部署运行一条龙服务之ant脚本
- 用maven管理项目,后加入tomcat中出现以下错误Failed to load or instantiate TagLibraryValidator class:
- Tomcat 部署 Web 通过 ip 直接访问项目
- 在Eclipse中使用Tomcat部署Web项目
- 如何让项目使用myEclipse部署在tomcat的ROOT目录下
- 使用maven部署项目到tomcat 7
- Java使用ExecutorService线程池通过Socket传输AES加密,并在客户端用ServerSocket解密