版权声明

最近很多爬虫来我博客爬文章,转载可以,但请保留原文出处及版权声明,即便是在中国

单纯的广告

个人博客:https://aodeng.cc
微信公众号:低调小熊猫
QQ群:756796932

简介

最近公司项目需要添加这个功能,听到软件注册码,我的第一反应就是破解,例如idea破解到2099年之类的(这年头谁花钱用正版啊),其实我听到这个功能需求是一脸懵逼的,因为我压根没搞过这玩意,只能到处查资料了,所幸功能还是搞出来了,苦逼的我,不bb了,写这篇文章就当加深印象了,也方便自己以后copy,最近越来越忙了,都没啥时间出来装逼了:(

使用

我们先看一下运行效果图,即便账号密码正确,也进不了系统,这样别人使用我们公司的产品,就需要购买我们公司提供的注册码,才能使用了,还是很nice的功能呢
file

首先介绍一个注解,这个注解在这个功能实现里面很重要了
@PostConstruct

PostConstruct 注释用于在依赖关系注入完成之后需要执行的方法上,以执行任何初始化。此方法必须在将类放入服务之前调用。支持依赖关系注入的所有类都必须支持此注释。即使类没有请求注入任何资源,用 PostConstruct 注释的方法也必须被调用。只有一个方法可以用此注释进行注释。应用 PostConstruct 注释的方法必须遵守以下所有标准:该方法不得有任何参数,除非是在 EJB 拦截器 (interceptor) 的情况下,根据 EJB 规范的定义,在这种情况下它将带有一个 InvocationContext 对象 ;该方法的返回类型必须为 void;该方法不得抛出已检查异常;应用 PostConstruct 的方法可以是 public、protected、package private 或 private;除了应用程序客户端之外,该方法不能是 static;该方法可以是 final;如果该方法抛出未检查异常,那么不得将类放入服务中,除非是能够处理异常并可从中恢复的 EJB。

1.serviceimpl实现类代码(这里是最重要的代码了)

@PostConstruct
    public void initAppRegedit() throws Exception {
        String classpath = this.getClass().getResource("/").getPath();
        File file = new File(classpath+"conf/config.properties");
        String macInfo = getMacInfo();
        if(file.exists()) {
            List<String> readLines = IOUtils.readLines(new FileInputStream(file), "utf-8");
            if(null!=readLines&&readLines.size()>0) {
                String key = readLines.get(0);
                String t = EncryptUtil.getInstance().DESdecode(key);
                if(StringUtils.equals(t, macInfo)) {
                    Const.APP_REGEDIT = true;
                }
            }
        }
        if(!Const.APP_REGEDIT) {
            List<String> lines = new ArrayList<>();
            lines.add(EncryptUtil.getInstance().DESencode(EncryptUtil.getInstance().DESencode(macInfo)));
            File outFile = new File(classpath+"conf/regedit.properties");
            IOUtils.writeLines(lines, "", new FileOutputStream(outFile), "utf-8");
        }
    }
    public static String getMacInfo() {
        String address = "";
        String os = System.getProperty("os.name");
        if (os != null && os.startsWith("Windows")) {
            try {
                String command = "cmd.exe /c ipconfig /all";
                Process p = Runtime.getRuntime().exec(command);
                BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String line;
                while ((line = br.readLine()) != null) {
                    if (line.indexOf("Physical Address") > 0||line.indexOf("物理地址") > 0) {
                        int index = line.indexOf(":");
                        index += 2;
                        address = line.substring(index);
                        break;
                    }
                }
                br.close();
            } catch (IOException e) {
                System.out.println("Error:" + e);
            }
        }
        return  address.trim();
    }

2.创建资源文件
file

3.我们在登录之前添加验证

if(!Const.APP_REGEDIT) {
            throw new InvalidRequestException(ErrorCodes.appRegeditFailed);
        }

Const是我们自定义的常量

public static boolean APP_REGEDIT = false;

ErrorCodes是我们自定义的异常

/**登录异常**/
public static String appRegeditFailed;

登录页面添加提示信息,这些都很简单,我就不贴代码了

4.创建加密工具包EncryptUtil

public static void main(String args[]){
        String regedit_key = "";
        System.out.println("密码:"+regedit_key);
        regedit_key = EncryptUtil.getInstance().DESdecode(regedit_key);
        System.out.println("注册码:"+regedit_key);
    }

这段代码就是将我们的密码加密,变成注册码,加密方式我采用的双向加密:DES、AES,代码就不贴了,百度一堆

5.运行项目之后class里面会生成两个文件
file

6.使用方式
项目启动后拷贝class/conf/regedit.properties内容到EncryptUtil中main中执行,后把注册码拷贝到class/conf/config.properties中即可

这样软件的注册码功能就实现了