# 忽略所有警告,否则有警告的时候混淆会停止
-ignorewarnings
# JDK目标版本1.8
-target 1.8
# 不做收缩(删除注释、未被引用代码)
-dontshrink
# 不做优化(变更代码实现逻辑)
-dontoptimize
# 不路过非公用类文件及成员
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
# 优化时允许访问并修改有修饰符的类和类的成员
-allowaccessmodification
# 确定统一的混淆类的成员名称来增加混淆
-useuniqueclassmembernames
# 不混淆所有包名,本人测试混淆后WEB项目问题实在太多,毕竟Spring配置中有大量固定写法的包名
-keeppackagenames
# 不混淆局部变量名
-keepparameternames
# 不混淆所有特殊的类 LocalVariable*Table,
#-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,Synthetic,EnclosingMethod
# 不混淆包下的所有类名
-keep class weg.base.** { <methods>; }
-keep class weg.service.** { <methods>; }
-keep class weg.dao.** { <methods>; }
-keep class weg.util.** { <methods>; }
# 不混淆quartz包下的所有类名,且类中的方法也不混淆
-keep class weg.quartz.** { <methods>; }
# 不混淆model包中的所有类以及类的属性及方法,实体包,混淆了会导致ORM框架及前端无法识别
-keep class weg.model.** {*;}
# 不混淆所有的set/get方法,毕竟项目中使用的部分第三方框架(例如Shiro)会用到大量的set/get映射
-keepclassmembers public class * {void set*(***);*** get*();}
# 保持类protected不被混淆
-keep public class * { public protected <fields>;public protected <methods>; }
package sdk;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.net.NetworkInterface;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
/**
* Created with IntelliJ IDEA.
*
* @Auther: ljt
* @Version 1.0
* @Date: 2020/09/01/10:32
* @Description:
*/
public class CheckActiveCode {
//向量(同时拥有向量和密匙才能解密),此向量必须是8byte,多少都报错
private static byte[] DESIV = new byte[] { 0x22, 0x54, 0x36, 110, 0x40, (byte) 0xac, (byte) 0xad, (byte) 0xdf };// 向量
private static AlgorithmParameterSpec iv = null;// 加密算法的参数接口
private static Key key = null;
private static String charset = "utf-8";
/**
* 激活码验证
* @param activeCode
* @return
* @throws Exception
*/
public static boolean verifyCode(String activeCode) throws Exception{
if(activeCode == null || "".equals(activeCode)){
//System.out.println("激活码为空");
return false;
}
String machineCode = activeCode.substring(0,32);
//System.out.println("机器码:"+ machineCode);
String dateCode = activeCode.substring(32);
//System.out.println("时间:"+ dateCode);
String mac = getMac().toUpperCase();
String code = new Md5PasswordEncoder().encodePassword(mac, "")
.toUpperCase() + mac.length();
String authCode = getSplitString(code).replace("-","");
if(!machineCode.equals(authCode) ){
throw new Exception("机器码不一致");
}
String md5Data = "";
try {
md5Data = decode(dateCode,machineCode);
} catch (Exception e) {
throw new Exception(e);
}
Date date= new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String newDate = sdf.format(date);
//System.out.println("加密日期:"+md5Data +",机器日期:"+newDate);
if("".equals(md5Data)){
//System.out.println("永久激活");
return true;
}
if(md5Data.compareTo(newDate) <0){
//System.out.println("激活码过期:["+activeCode+"]");
return false;
}
//System.out.println("激活成功");
return true;
}
private static String getMac() {
try {
Enumeration<NetworkInterface> el = NetworkInterface
.getNetworkInterfaces();
while (el.hasMoreElements()) {
byte[] mac = el.nextElement().getHardwareAddress();
if (mac == null)
continue;
String hexstr = bytesToHexString(mac);
return getSplitString(hexstr, "-", 2).toUpperCase();
}
} catch (Exception exception) {
exception.printStackTrace();
}
return null;
}
private static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
private static String getSplitString(String str) {
return getSplitString(str, "-", 4);
}
private static String getSplitString(String str, String split, int length) {
int len = str.length();
StringBuilder temp = new StringBuilder();
for (int i = 0; i < len; i++) {
if (i % length == 0 && i > 0) {
temp.append(split);
}
temp.append(str.charAt(i));
}
String[] attrs = temp.toString().split(split);
StringBuilder finalMachineCode = new StringBuilder();
for (String attr : attrs) {
if (attr.length() == length) {
finalMachineCode.append(attr).append(split);
}
}
String result = finalMachineCode.toString().substring(0,
finalMachineCode.toString().length() - 1);
return result;
}
/**
* 解密
* @param data
* @return
* @throws Exception
*/
private static String decode(String data,String deSkey) throws Exception {
DESKeySpec keySpec = new DESKeySpec(deSkey.getBytes(charset));// 设置密钥参数
iv = new IvParameterSpec(DESIV);// 设置向量
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");// 获得密钥工厂
key = keyFactory.generateSecret(keySpec);// 得到密钥对象
Cipher deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
deCipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] pasByte = deCipher.doFinal(toBytes(data));
return new String(pasByte, charset);
}
/**
* 获取MD5的值,可用于对比校验
* @param sourceStr
* @return
*/
private static String getMD5Value(String sourceStr) {
String result = "";
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(sourceStr.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
result = buf.toString();
} catch (NoSuchAlgorithmException e) {
}
return result;
}
/**
* 将16进制字符串转换为byte[]
*
* @param str
* @return
*/
private static byte[] toBytes(String str) {
if(str == null || str.trim().equals("")) {
return new byte[0];
}
byte[] bytes = new byte[str.length() / 2];
for(int i = 0; i < str.length() / 2; i++) {
String subStr = str.substring(i * 2, i * 2 + 2);
bytes[i] = (byte) Integer.parseInt(subStr, 16);
}
return bytes;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>sdk-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.0.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- ProGuard混淆插件-->
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.0.11</version>
<executions>
<execution>
<!-- 混淆时刻,这里是打包的时候混淆-->
<phase>package</phase>
<goals>
<!-- 指定使用插件的混淆功能 -->
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 是否将生成的PG文件安装部署-->
<attach>true</attach>
<!-- 是否混淆-->
<obfuscate>true</obfuscate>
<!-- 指定生成文件分类 -->
<attachArtifactClassifier>pg</attachArtifactClassifier>
<proguardInclude>${basedir}/proguard.conf</proguardInclude>
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jce.jar</lib>
</libs>
<!-- 对什么东西进行加载,这里仅有classes成功,不可能对配置文件及JSP混淆吧-->
<injar>classes</injar>
<outjar>${project.build.finalName}-pg.jar</outjar>
<!-- 输出目录-->
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>