使用类加载器加密字节码文件时:项目中如何使用自定义的类加载器

小老犇 2021-02-22 04:06:35
我的步骤如下:
1、将所有的字节码文件加密后放入tomcat的webapp下。
2、在tomcat中配置自定义的类加载器。
3、在类加载器中打破双亲委派机制,凡是名称为自己包名的就走自己的加载器。

诸位大神,思路有没有错误的地方
...全文
523 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
hbhbhbhbhb1021 2021-03-12
  • 打赏
  • 举报
回复
操作风险有点大哦,看这个是做什么的,比如规则引擎的编辑规则服务,这种使用自定义类加载器,对生产业务没影响,到也无所谓。 以前写的例子,可以参考看看,简单说就是继承ClassLoader,还需要把加载的类进行代理

package org.firewater.compile_code;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;

public class FireWaterClassLoader extends ClassLoader {
    private File classPathFile;
    public FireWaterClassLoader(){
        String classPath = FireWaterClassLoader.class.getResource("").getPath();
        this.classPathFile = new File(classPath);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {

        String className = FireWaterClassLoader.class.getPackage().getName() + "." + name;
        if(classPathFile  != null){
            File classFile = new File(classPathFile,name.replaceAll("\\.","/") + ".class");
            if(classFile.exists()){
                FileInputStream in = null;
                ByteArrayOutputStream out = null;
                try{
                    in = new FileInputStream(classFile);
                    out = new ByteArrayOutputStream();
                    byte [] buff = new byte[1024];
                    int len;
                    while ((len = in.read(buff)) != -1){
                        out.write(buff,0,len);
                    }
                    return defineClass(className,out.toByteArray(),0,out.size());
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}
package org.firewater.compile_code;
/*
* 类需要实现的接口
* */
public interface ClassInterface {
    public int add();
    public void printString();
}
package org.firewater.compile_code;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class InitClass {
    private static String crlf="\r\n";
    public static String generatorCode(){
        StringBuffer sb=new StringBuffer();
        sb.append("package org.firewater.compile_code;").append(crlf);
        sb.append("public class SimpleClass1 implements  ClassInterface{").append(crlf)
                .append("private int a;").append(crlf)
                .append("private int b;").append(crlf)
                .append("private String c;").append(crlf)
                .append("public SimpleClass1(int a, int b, String c) {").append(crlf)
                .append("this.a = a;").append(crlf)
                .append("this.b = b;").append(crlf)
                .append("this.c = c;").append(crlf)
                .append("}").append(crlf)
                .append("public int add(){").append(crlf)
                .append("int d=this.a+this.b;").append(crlf)
                .append("System.out.println(\"d====:“\"+d+\"”\");").append(crlf)
                .append(" return d;").append(crlf)
                .append("}").append(crlf)
                .append("public void printString(){").append(crlf)
                .append("System.out.println(\"c====:“\"+c+\"”\");").append(crlf)
                .append("}").append(crlf)
                .append("}").append(crlf);
        return sb.toString();
    }
    public static Object newObjectInstance() throws IOException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException, NoSuchMethodException {
        //生成Java 源码
        String code = generatorCode();
        //输出到磁盘
        String filePath = InitClass.class.getResource("").getPath();
        File f = new File(filePath + "SimpleClass1.java");
        FileWriter fw = new FileWriter(f);
        fw.write(code);
        fw.flush();
        fw.close();

        //编译成class
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager manage = compiler.getStandardFileManager(null,null,null);
        Iterable iterable = manage.getJavaFileObjects(f);
        JavaCompiler.CompilationTask task = compiler.getTask(null,manage,null,null,null,iterable);
        task.call();
        manage.close();

        //使用类加载机制加载class
        FireWaterClassLoader classLoader=new  FireWaterClassLoader();

        Class clazz =    classLoader.findClass("SimpleClass1");
        Constructor c = clazz.getConstructor(int.class,int.class,String.class);
        f.delete();
        Object o = c.newInstance(1, 2,"3333");
        return o;
    }

}
package org.firewater.compile_code;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

public class TestMain {
    public static void main(String[] args)  {
        try {
            ClassInterface classInterface=(ClassInterface)InitClass.newObjectInstance();
            classInterface.add();
            classInterface.printString();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}
树成 2021-03-12
  • 打赏
  • 举报
回复
引用 4 楼 小老犇 的回复:
[quote=引用 3 楼 树成的回复:][quote=引用 2 楼 小老犇 的回复:]某些加密字节码文件需要指定自定义类加载器加载,需要打破双亲委派模型,这种例子很多,tomcat,nginx等等。 字节码文件部署在甲方,甲方可以任意反编译,源码泄漏问题。
指定类装载器装载类并不需要打破双亲委派模型,所有类都是由启动类装载器开始装载,启动类装载器装载不了再委派给子装载器装载然后依次递归,这就是委派模型,你不可能打破这个模型,因为都绕不开启动类装载器,否则java无法启动,而且也不需要打破委派模型,直接指定类装载器就可以装载。 另外,既然你的字节码都部署在客户机,加密不加密根本不重要,因为你类装载器本身就包含解密信息,你不大可能屏蔽这个东西,因为你整个项目都部署在客户机,如果客户有本事反编译字节码,那找出你的类装载器找到解密信息是一件很简单事情,而加密class文件带来的风险和工作量非常大,根本得不偿失。 另外不得不提一个现实的问题,你的代码没那么重要。如果你的实现算法真的非常NB,你可以直接申请专利,用不着操这种心,要不然,网上类似的东西到处都能抄到。[/quote] 这个老哥辛苦了,这么多字不容易,感谢! 我个人理解: 所谓的打破双亲委派模型,并不影响那三个类加载器启动扩展应用程序类加载器的双亲委派,只不过是嵌入了一段代码,指定类加载器加载自己的类。 另外自己的类加载器字节码文件并不一定要放在tomcat下,可以放在远程服务器,也可以放在配套的JDK下进行加载,避免别人很轻易的找到。 这个需求纯粹是领导想要遮掩二次开发的痕迹,怕别人看到是个开源的项目,哈哈。[/quote] 判断是不是开源项目,看目录结构和配置文件就行了,并不需要去看源码,如果没有接触过对应的开源项目,估计也不知道是开源项目,如果接触过,基本上不用看源码也知道是。
树成 2021-03-12
  • 打赏
  • 举报
回复
引用 6 楼 maradona1984 的回复:
[quote=引用 3 楼 树成 的回复:][quote=引用 2 楼 小老犇 的回复:]某些加密字节码文件需要指定自定义类加载器加载,需要打破双亲委派模型,这种例子很多,tomcat,nginx等等。 字节码文件部署在甲方,甲方可以任意反编译,源码泄漏问题。
指定类装载器装载类并不需要打破双亲委派模型,所有类都是由启动类装载器开始装载,启动类装载器装载不了再委派给子装载器装载然后依次递归,这就是委派模型,你不可能打破这个模型,因为都绕不开启动类装载器,否则java无法启动,而且也不需要打破委派模型,直接指定类装载器就可以装载。 另外,既然你的字节码都部署在客户机,加密不加密根本不重要,因为你类装载器本身就包含解密信息,你不大可能屏蔽这个东西,因为你整个项目都部署在客户机,如果客户有本事反编译字节码,那找出你的类装载器找到解密信息是一件很简单事情,而加密class文件带来的风险和工作量非常大,根本得不偿失。 另外不得不提一个现实的问题,你的代码没那么重要。如果你的实现算法真的非常NB,你可以直接申请专利,用不着操这种心,要不然,网上类似的东西到处都能抄到。[/quote] 这个想找出来也不算件简单的事情,总得对tomcat源码比较熟悉才行,一般来说买这种成品软件的公司技术实力一般[/quote] 如果客户懂得反编译字节码的,要找出加密基本不难,如果找不出加密信息,基本也不去反编译字节码。
maradona1984 2021-03-11
  • 打赏
  • 举报
回复
引用 3 楼 树成 的回复:
[quote=引用 2 楼 小老犇 的回复:]某些加密字节码文件需要指定自定义类加载器加载,需要打破双亲委派模型,这种例子很多,tomcat,nginx等等。 字节码文件部署在甲方,甲方可以任意反编译,源码泄漏问题。
指定类装载器装载类并不需要打破双亲委派模型,所有类都是由启动类装载器开始装载,启动类装载器装载不了再委派给子装载器装载然后依次递归,这就是委派模型,你不可能打破这个模型,因为都绕不开启动类装载器,否则java无法启动,而且也不需要打破委派模型,直接指定类装载器就可以装载。 另外,既然你的字节码都部署在客户机,加密不加密根本不重要,因为你类装载器本身就包含解密信息,你不大可能屏蔽这个东西,因为你整个项目都部署在客户机,如果客户有本事反编译字节码,那找出你的类装载器找到解密信息是一件很简单事情,而加密class文件带来的风险和工作量非常大,根本得不偿失。 另外不得不提一个现实的问题,你的代码没那么重要。如果你的实现算法真的非常NB,你可以直接申请专利,用不着操这种心,要不然,网上类似的东西到处都能抄到。[/quote] 这个想找出来也不算件简单的事情,总得对tomcat源码比较熟悉才行,一般来说买这种成品软件的公司技术实力一般
小老犇 2021-03-10
  • 打赏
  • 举报
回复
引用 3 楼 树成的回复:
[quote=引用 2 楼 小老犇 的回复:]某些加密字节码文件需要指定自定义类加载器加载,需要打破双亲委派模型,这种例子很多,tomcat,nginx等等。 字节码文件部署在甲方,甲方可以任意反编译,源码泄漏问题。
指定类装载器装载类并不需要打破双亲委派模型,所有类都是由启动类装载器开始装载,启动类装载器装载不了再委派给子装载器装载然后依次递归,这就是委派模型,你不可能打破这个模型,因为都绕不开启动类装载器,否则java无法启动,而且也不需要打破委派模型,直接指定类装载器就可以装载。 另外,既然你的字节码都部署在客户机,加密不加密根本不重要,因为你类装载器本身就包含解密信息,你不大可能屏蔽这个东西,因为你整个项目都部署在客户机,如果客户有本事反编译字节码,那找出你的类装载器找到解密信息是一件很简单事情,而加密class文件带来的风险和工作量非常大,根本得不偿失。 另外不得不提一个现实的问题,你的代码没那么重要。如果你的实现算法真的非常NB,你可以直接申请专利,用不着操这种心,要不然,网上类似的东西到处都能抄到。[/quote] 这个老哥辛苦了,这么多字不容易,感谢! 我个人理解: 所谓的打破双亲委派模型,并不影响那三个类加载器启动扩展应用程序类加载器的双亲委派,只不过是嵌入了一段代码,指定类加载器加载自己的类。 另外自己的类加载器字节码文件并不一定要放在tomcat下,可以放在远程服务器,也可以放在配套的JDK下进行加载,避免别人很轻易的找到。 这个需求纯粹是领导想要遮掩二次开发的痕迹,怕别人看到是个开源的项目,哈哈。
小老犇 2021-03-10
  • 打赏
  • 举报
回复
某些加密字节码文件需要指定自定义类加载器加载,需要打破双亲委派模型,这种例子很多,tomcat,nginx等等。 字节码文件部署在甲方,甲方可以任意反编译,源码泄漏问题。
树成 2021-03-10
  • 打赏
  • 举报
回复
java的双亲委派模型是固定模型吧,不知道你要如何打破,也不知道你为何要打破。 class文件为什么要加密?这是一个没有意义的需求吧? 由某个类装载器装载以后的类其引用类都会用该类装载器装载。
树成 2021-03-10
  • 打赏
  • 举报
回复
引用 2 楼 小老犇 的回复:
某些加密字节码文件需要指定自定义类加载器加载,需要打破双亲委派模型,这种例子很多,tomcat,nginx等等。 字节码文件部署在甲方,甲方可以任意反编译,源码泄漏问题。
指定类装载器装载类并不需要打破双亲委派模型,所有类都是由启动类装载器开始装载,启动类装载器装载不了再委派给子装载器装载然后依次递归,这就是委派模型,你不可能打破这个模型,因为都绕不开启动类装载器,否则java无法启动,而且也不需要打破委派模型,直接指定类装载器就可以装载。 另外,既然你的字节码都部署在客户机,加密不加密根本不重要,因为你类装载器本身就包含解密信息,你不大可能屏蔽这个东西,因为你整个项目都部署在客户机,如果客户有本事反编译字节码,那找出你的类装载器找到解密信息是一件很简单事情,而加密class文件带来的风险和工作量非常大,根本得不偿失。 另外不得不提一个现实的问题,你的代码没那么重要。如果你的实现算法真的非常NB,你可以直接申请专利,用不着操这种心,要不然,网上类似的东西到处都能抄到。

67,549

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧