版权声明

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

  • 本文作者:低调小熊猫

单纯的广告

个人博客: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中即可

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