JavaEE防盗版

本文探讨了JavaEE项目的防盗版策略,包括基于Java License的付费时效验证、ProGuard混淆技术增强代码安全性,以及类加载器加密思路。重点介绍了类加载机制、双亲委派模型,以及ProGuard混淆配置。此外,还提到了使用Truelicense进行License开发,生成和验证证书的过程。
摘要由CSDN通过智能技术生成

前言

      本文要是提供一个思路,用于设计javaWeb项目的防盗版技术(针对付费产品的防盗版)。研究背景在于没有一家公司愿意将自己的产品项目被目标客户破解使用,造成研发公司的重大财产损失。

      这里主要提供的是开发思路,由于保密协议的关系,源码不能完全贴出。因此大家参考思路以后自行进行逻辑实现。

      研发思路如下:

  1. 基于java的License进行付费时效验证,验证代码可用其它语言进行开发(JAVA实在太容易反编译了)。
  2. 对核心代码进行混淆,增加反编译的阅读难度(这里可以尽可能多的将业务逻辑拆分成多个私有方法进行开发,毕竟public方法还是不要混淆的好)。
  3. 对核心代码进行加密,也就是对外暴露的class文件是不能够直接进行反编译的,需要进行解密!这里就涉及到了类加载的问题。因此,本文也会对java的类加载机制进行一个简单的叙述。

      以上就是整体的研发思路了,当然,思路可能比较简单,并且部分的解密代码可以使用C语言来进行开发,毕竟C反汇编阅读起来也是比较困难的。另外,在实际开发中也可以在一些业务逻辑中进行校验,使得破解更加费时费力。

java之类加载

        类加载技术是java运行的核心部分之一,虽然对于开发来说运用到此技术的地方不多,但是作为JAVAEE防盗版技术的组成部分之一,这一部分对于研发来说也需要着重了解。

本文分析对象针对于:JDK1.7

JVM预定义的三种类加载器

1.启动类加载器:启动类装入器是用本地代码实现的类装入器,它负责将JRE/lib下面的核心类库或-Xbootclasspath选项指定的jar包加载到内存中。由于其涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用

2.扩展类加载器:扩展类加载器是由Sun的ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将JRE/lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。

3.系统类加载器:系统类加载器是由 Sun的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径java -classpath-Djava.class.path变量所指的目录下的类库加载到内存中。开发者可以直接使用系统类加载器。

类加载的双亲委派机制

        JVM在加载类时默认采用的是双亲委派机制。通俗的讲,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。关于虚拟机默认的双亲委派机制,我们可以从系统类加载器和扩展类加载器为例作简单分析。

图1.1 ExtClassLoader和AppClassLoader继承结构图

      由图1.1可以看到,扩展类加载器和系统类加载器的层次结构一致,并且查看源码可知,系统类加载器的构造器和扩展类加载器的构造器在创建时最终都会调用ClassLoader的带参构造器,并将父构造器注册到其中(图1.2)。

图1.2 扩展类加载器的构建过程,指定父类加载器为null

      由于可以看出来,扩展类加载器在构建时候就指定了父加载器,并且ClassLoader类的parent方法权限为private,并且没有提供setter方法。并且扩展类加载器的父加载器被设置为了null。

      同理,系统类加载器的父加载器被设置为了ExtClassLoader(图1.3)。

图1.3 系统类加载器的构建过程,指定父类加载器为ExtClassLoader

      用代码来检测一下:

package com.noryar.classloader.test;  
public class ClassLoaderTest {  
    public static void main(String[] args) {  
        System.out.println("系统类加载器为:"+ClassLoader.getSystemClassLoader());  
        System.out.println("扩展类加载器为:"+ClassLoader.getSystemClassLoader().getParent());  
        System.out.println("启动类加载器为:"+ClassLoader.getSystemClassLoader().getParent().getParent());  
    }  
}  

      运行结果如下,符合预期:


系统类加载器为:sun.misc.Launcher$AppClassLoader@1b31c23  
扩展类加载器为:sun.misc.Launcher$ExtClassLoader@1fc7b3a  
启动类加载器为:null  

      OK,说了这么多,接下来介绍一下双亲委派机制的实现。首先我们分析一下ClassLoader这个抽象类的几个重要方法。

public abstract class ClassLoader {  
    // 用指定的二进制名称加载类,它会通知JVM去解析类信息。  
    public Class<?> loadClass(String name) throws ClassNotFoundException {  
        return loadClass(name, false);  
    }  
  
    // 用指定的二进制名称加载类,具体的实现流程如下:  
    // 1. 使用findLoadedClass(String)方法来检测该类是否已被加载  
    // 2. 调用父加载器的loadClass(String)方法,这里就是双亲委派机制的实现逻辑  
    // 3. 调用findClass来寻找类  
    protected Class<?> loadClass(String name, boolean resolve)  
        throws ClassNotFoundException  
    {  
        ....  
    }  
      
    // 使用指定的二进制名称寻找类。该应当在ClassLoader的子类中进行重写,并且会被loadClass方法调用。  
    protected Class<?> findClass(String name) throws ClassNotFoundException {  
        throw new ClassNotFoundException(name);  
    }  
      
    // 将字节码文件转换成实体类,被findClass方法调用  
    // 次方法调用本地方法,因此在开发中无需复写。  
    protected final Class<?> defineClass(String name, byte[] b, int off, int len,  
                                         ProtectionDomain protectionDomain)  
        throws ClassFormatError  
    {  
        ....  
     }  
}  

      检查发现ClassLoader的子类只对loadClass方法进行了扩展(主要是增加了一些校验),并没有对其调用机理做根本改变,因此,双亲委派机制的实现只要分析ClassLoader的loadClass(String name, boolean resolve)方法即可。下面是该方法的具体实现(图1.4)。

图1.4 ClassLoader的loadClass方法实现

      综上所述,当一个类需要加载的时候,当前类加载器就会一级一级的调用系统

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值