个人博客:https://aodeng.cc
微信公众号:低调小熊猫
QQ群:756796932
最近公司项目需要添加这个功能,听到软件注册码,我的第一反应就是破解,例如idea破解到2099年之类的(这年头谁花钱用正版啊),其实我听到这个功能需求是一脸懵逼的,因为我压根没搞过这玩意,只能到处查资料了,所幸功能还是搞出来了,苦逼的我,不bb了,写这篇文章就当加深印象了,也方便自己以后copy,最近越来越忙了,都没啥时间出来装逼了:(
我们先看一下运行效果图,即便账号密码正确,也进不了系统,这样别人使用我们公司的产品,就需要购买我们公司提供的注册码,才能使用了,还是很nice的功能呢
首先介绍一个注解,这个注解在这个功能实现里面很重要了
@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.创建资源文件
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里面会生成两个文件
6.使用方式
项目启动后拷贝class/conf/regedit.properties内容到EncryptUtil中main中执行,后把注册码拷贝到class/conf/config.properties中即可
这样软件的注册码功能就实现了