springboot整合License授权控制

yml配置文件设置读取licenses文件位置 

license:
  filePath: "D://licenses.lc"

 创建licenses文件码


import sun.misc.BASE64Encoder;

import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 许可文件的生成类<br>
 * 只用于在公司内网生成许可文件,不得出公司内网、更不得打包到项目中
 * @author lidaquan
 *
 */
public class LicenseMaker {

    private static final String TYPE_DATE = "date";

    private static final String TYPE_DATE_DW = "date_hw";

    private static final String OS_WINDOWS = "Windows";

    private static final String OS_LINUX = "Linux";

    private static final String OS_AIX = "AIX";

    private static final String FAKE_MAC = "abcdef123456";

    /**
     *
     * @param type
     * @param endDay
     * @param osArray 如果macAddressArray不为空,则osArray与macAddressArray的个数必须相同
     * @param macAddressArray 单实例环境与单机集群环境均为一个,多机集群环境为多个;不管什么环境,对于每台机器应该只允许一个;出于保护目的,目前最多允许4个;如果不是基于硬件的许可,可以设为null
     * @param serie 从技术上控制可以使用该许可的项目类别(可以达到强制控制的目的,但无法细化到具体项目或用户)
     * @param user  从字面上声明可以使用该许可的项目名称或用户名称(无法达到强制控制的目的,但可以细化到具体项目或用户)
     */
    public static void create(String type, String endDay, String[] osArray, String[] macAddressArray, String serie, String user){
        String osSet = "";
        String macAddressSet = "";
        if(type == null || "".equals(type) || endDay == null || "".equals(endDay) || osArray == null || osArray.length == 0 || serie == null || "".equals(serie) || user == null || "".equals(user)){
            throw new IllegalArgumentException("参数不能为空");
        }else if(TYPE_DATE_DW.equals(type)){
//            if(macAddressArray == null || macAddressArray.length == 0){
//                throw new IllegalArgumentException("参数不能为空");
//            }
//            if(macAddressArray.length > 4){
//                throw new IllegalArgumentException("参数超过上限");
//            }
//            if(osArray.length != macAddressArray.length){
//                throw new IllegalArgumentException("osArray与macAddressArray的数量不一致");
//            }
            for(int i = 0, size = osArray.length;i < size;i++){
                String os = osArray[i];
                if(os == null || "".equals(os)){
                    throw new IllegalArgumentException("参数不能为空");
                }
//                String macAddress = macAddressArray[i];
//                if(macAddress == null || "".equals(macAddress) || macAddress.length() != 12){
//                    throw new IllegalArgumentException("参数不能为空并且长度必须为12位");
//                }
                osSet += os;
//                macAddressSet += macAddress;
                if(i < size - 1){
                    osSet += "_";
//                    macAddressSet += "_";
                }
            }
        }else if(TYPE_DATE.equals(type)){
            if(osArray.length > 1){
                throw new IllegalArgumentException("参数超过上限");
            }
            osSet = osArray[0];
        }
        try{
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date endDate = dateFormat.parse(endDay);
            Date now = new Date();
            Date authDate = new Date(now.getYear(), now.getMonth(), now.getDate());

            System.out.println("许可颁发类型:" + type);
            System.out.println("许可结束日期:" + dateFormat.format(endDate));
            System.out.println("许可颁发日期:" + dateFormat.format(authDate));
            System.out.println("许可适用系统:" + osSet);
            System.out.println("许可颁发网卡:" + macAddressSet);
            System.out.println("许可颁发产品:" + serie);
            System.out.println("许可颁发用户:" + user);
            System.out.println("---------------------------------------------------------------");

            MessageDigest md = MessageDigest.getInstance("SHA-1");
            System.out.print("serial=");
            System.out.print(encode(type));
            md.update(type.getBytes());
            byte[] degist = md.digest();
            System.out.print("-" + new BASE64Encoder().encode(degist));

            String endDateStr = dateFormat.format(endDate);
            System.out.print("-" + encode(endDateStr));
            md.update(endDateStr.getBytes());
            degist = md.digest();
            System.out.print("-" + new BASE64Encoder().encode(degist));

            String authDateStr = dateFormat.format(authDate);
            System.out.print("-" + encode(authDateStr));
            md.update(authDateStr.getBytes());
            degist = md.digest();
            System.out.print("-" + new BASE64Encoder().encode(degist));

            System.out.print("-" + encode(osSet));
            md.update(osSet.getBytes());
            degist = md.digest();
            System.out.print("-" + new BASE64Encoder().encode(degist));

            if(TYPE_DATE.equals(type)){
                macAddressSet = FAKE_MAC;
            }else{
                macAddressSet = macAddressSet.toLowerCase();
            }
            System.out.print("-" + encode(macAddressSet));
            md.update(macAddressSet.getBytes());
            degist = md.digest();
            System.out.print("-" + new BASE64Encoder().encode(degist));

            System.out.print("-" + encode(serie));
            md.update(serie.getBytes());
            degist = md.digest();
            System.out.print("-" + new BASE64Encoder().encode(degist));

            System.out.print("-" + encode(user));
            md.update(user.getBytes());
            degist = md.digest();
            System.out.print("-" + new BASE64Encoder().encode(degist));

        }catch(Exception e){
            e.printStackTrace();
        }
    }

    private static String encode(String msg){
        byte[] code = msg.getBytes();
        exchangeCode(code);
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(code);
    }

    private static void exchangeCode(byte[] code){
        int i, iSize;
        iSize = code.length/8;
        for (i = 0;i < iSize;i++){
            exchange(code, i*8 + 7, i*8);
            exchange(code, i*8 + 5, i*8 + 2);
        }
    }

    private static void exchange(byte[] code, int i, int j){
        byte temp = code[i];
        code[i] = code[j];
        code[j] = temp;
    }

    public static void main(String[] args){
       
        create(TYPE_DATE_DW, "2025-02-04", new String[]{OS_LINUX, OS_WINDOWS}, new String[]{}, "appName", "appChineseName");
    }

}

/**
 * ${appName}的许可标识<br>
 * 只允许用于${appName}的项目
 *
 */
public class LicenseChecker_appName extends LicenseChecker {

	public static final String SERIE = "appName";

	@Override
	protected String getSerie() {

		return SERIE;
	}

}

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.net.NetworkInterface;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;

/**
 * 许可文件的校验类<br>
 * 随同许可文件打包到项目中
 *
 * @author bo a bo
 */
public abstract class LicenseChecker {

    public boolean check() {
        boolean valid = false;
        try {
            String serial = ReadLicenseUtils.readLicense();
            if (StringUtil.isEmpty(serial)) {
                throw new RuntimeException();// 未读取到license
            }
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            String type = decode(serial.split("-")[0]);
            md.update(type.getBytes());
            String degistStr = new BASE64Encoder().encode(md.digest());
            if (!serial.split("-")[1].equals(degistStr)) {
                throw new RuntimeException();//许可颁发类型的序列号摘要不对
            }

            String endDateStr = decode(serial.split("-")[2]);
            md.update(endDateStr.getBytes());
            degistStr = new BASE64Encoder().encode(md.digest());
            if (!serial.split("-")[3].equals(degistStr)) {
                throw new RuntimeException();//许可结束日期的序列号摘要不对
            }

            String authDateStr = decode(serial.split("-")[4]);
            md.update(authDateStr.getBytes());
            degistStr = new BASE64Encoder().encode(md.digest());
            if (!serial.split("-")[5].equals(degistStr)) {
                throw new RuntimeException();//许可颁发日期的序列号摘要不对
            }

            String osSet = decode(serial.split("-")[6]);
            md.update(osSet.getBytes());
            degistStr = new BASE64Encoder().encode(md.digest());
            if (!serial.split("-")[7].equals(degistStr)) {
                throw new RuntimeException();//许可适用系统的序列号摘要不对
            }

            String hwSet = decode(serial.split("-")[8]);
            md.update(hwSet.getBytes());
            degistStr = new BASE64Encoder().encode(md.digest());
            if (!serial.split("-")[9].equals(degistStr)) {
                throw new RuntimeException();//许可颁发网卡的序列号摘要不对
            }

            String serie = decode(serial.split("-")[10]);
            md.update(serie.getBytes());
            degistStr = new BASE64Encoder().encode(md.digest());
            if (!serial.split("-")[11].equals(degistStr)) {
                throw new RuntimeException();//许可颁发产品的序列号摘要不对
            }

            String user = decode(serial.split("-")[12]);
            md.update(user.getBytes());
            degistStr = new BASE64Encoder().encode(md.digest());
            if (!serial.split("-")[13].equals(degistStr)) {
                throw new RuntimeException();//许可颁发用户的序列号摘要不对
            }

            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date endDate = dateFormat.parse(endDateStr);
            Date authDate = dateFormat.parse(authDateStr);
            Date now = new Date();
            Date today = new Date(now.getYear(), now.getMonth(), now.getDate());
            if (endDate.compareTo(today) >= 0 && authDate.compareTo(today) <= 0 && this.getSerie().equals(serie)) {
                if ("date".equals(type) && System.getProperty("os.name").startsWith(osSet)) {
                    valid = true;
                }/*else if("devel".equals(user)){//这个分支用于方便开发人员在本地进行开发“绑定硬件的许可类型”的项目;只在项目工程的 WEB-INF\lib\ 目录下使用,在SVN上一定要注释掉(避免此分支出现在非本地开发环境)!!!
					valid = true;
				}*/ else {
                    String[] osArray = osSet.split("_");
                    if (!StringUtil.isEmpty(hwSet)) {
                        String[] hwArray = hwSet.split("_");
                        Enumeration<NetworkInterface> niel = NetworkInterface.getNetworkInterfaces();
                        allNetworkInterface:
                        while (niel.hasMoreElements()) {
                            NetworkInterface ni = niel.nextElement();
                            byte[] mac = ni.getHardwareAddress();
                            if (mac == null || mac.length != 6) {
                                continue;
                            }
                            StringBuffer macBuffer = new StringBuffer();
                            for (int i = 0, size = mac.length; i < size; i++) {
                                String s = "0" + Integer.toHexString(mac[i]);
                                s = s.substring(s.length() - 2);
                                macBuffer.append(s);
                            }
                            for (int i = 0; i < hwArray.length; i++) {
                                String hw = hwArray[i];
                                String os = osArray[i];
                                if (macBuffer.toString().equals(hw) && System.getProperty("os.name").startsWith(os)) {
                                    valid = true;
                                    break allNetworkInterface;
                                }
                            }
                        }
                    } else {
                        for (int i = 0; i < osArray.length; i++) {
                            String os = osArray[i];
                            if (System.getProperty("os.name").startsWith(os)) {
                                valid = true;
                                break;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
        }
        return valid;
    }

    protected abstract String getSerie();

    private static String decode(String dec) {
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] code = decoder.decodeBuffer(dec);
            vexchangeCode(code);
            return new String(code);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    private static void vexchangeCode(byte[] code) {
        int i, iSize;
        iSize = code.length / 8;
        for (i = 0; i < iSize; i++) {
            exchange(code, i * 8 + 2, i * 8 + 5);
            exchange(code, i * 8, i * 8 + 7);
        }
    }

    private static void exchange(byte[] code, int i, int j) {
        byte temp = code[i];
        code[i] = code[j];
        code[j] = temp;
    }

}

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author bo a bo
 */
@Data
@Component
@ConfigurationProperties(value = "license")
public class LicenseProperties {

    private String filePath;

    private String value;

    /**
     * 是否开启全局拦截,默认开启
     */
    private Boolean enabled = Boolean.TRUE;

    /**
     * 当不开启全局拦截时,需要配置哪些url需要拦截
     */
    private List<String> urlList;

}

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
import java.util.Properties;

public class ReadLicenseUtils {

    private static final String licenseFile = "licenses.lc";//在AIX7.1中,文件名必须加后缀,否则无法读取

    public static String readLicense() {
        LicenseProperties licenseProperties = null;
        try {
            licenseProperties = SpringUtil.getBean(LicenseProperties.class);
        } catch (Exception e) {
            licenseProperties = new LicenseProperties();
        }
        String filePath = licenseProperties.getFilePath();
        String license = null;
        if (FileUtil.exist(filePath)) {
            // 当配置的文件存在时,读取文件中的license
            try {
                license = FileUtil.readLine(new RandomAccessFile(filePath, "r"), StandardCharsets.UTF_8);
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
        if (StrUtil.isNotBlank(license)) {
            return license;
        }
        // 当文件不存在,获取读取内容为空时,使用配置中的licesne
        license = licenseProperties.getValue();
        if (StrUtil.isNotBlank(license)) {
            return license;
        }
//        license = ResourceUtil.readStr(licenseFile, StandardCharsets.UTF_8);
//        if (StrUtil.isNotBlank(license)) {
//            return license;
//        }
//        license = ResourceUtil.readStr("/" + licenseFile, StandardCharsets.UTF_8);
//        if (StrUtil.isNotBlank(license)) {
//            return license;
//        }
//        return null;
        // 当配置中的license为空时,读取resources中的licenses.lc文件中的license
        InputStream is = null;
        try {
            Properties prop = new Properties();
            ClassLoader classLoader = ReadLicenseUtils.class.getClassLoader();
            is = classLoader.getResourceAsStream("/" + licenseFile);//某些JDK、中间件要加“/”
            if (is == null || is.available() == 0) {
                is = classLoader.getResourceAsStream(licenseFile);//某些JDK、中间件不加“/”
            }
            prop.load(is);
            String serial = prop.getProperty("serial");
            return serial;
        } catch (Exception e) {
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                }
            }
        }
        return null;
    }

}
/**
 * 字符串工具类
 * @author bo a bo
 *
 */
public class StringUtil {

	/**
	 * 字符串是否为空(null、空串、空格、"null")
	 * @param s
	 * @return
	 */
	public static boolean isEmpty(String s){
		if(s == null || "".equals(s.trim()) || "null".equalsIgnoreCase(s.trim())){
			return true;
		}
		return false;
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值