当前位置:   article > 正文

一种软件license授权设计案例_软件授权license

软件授权license

一种软件license授权设计案例

整体设计思路

license服务器端:
--负责根据客户端systemSign颁发证书。
--使用dom4j生成lic.xml证书
--使用AES对xml关键节点进行数据加密
--lic证书生成时设定信息包括:
-----客户端systemSign
-----生效起始时间
-----生效截止时间
-----上一次校验时间
-----项目版本号
-----license文件生成路径

license客户端:
--负责生成systemSign客户端系统签名
--证书检验/定时验证/自助更新(手动替换)
--API管控(无lic证书,则无法访问系统功能API)
--证书校验逻辑:
-----lic.xml文件存不存在
-----解析xml是否异常!
-----解密signature签名是否成功
-----解析版本号、lic生成时间、lic过期时间、上一次校验时间
-----校验本机app版本号与license版本号是否不一致
-----校验mac地址与本机是否一致
-----校验cpu序列号与本机是否一致
---证书过期判定:
------上次校验时间 大于当前系统时间
------lic证书生成时间 大于当前系统时间
------lic证书过期时间 小于当前系统时间
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

需要引入的依赖

 		<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.11</version>
        </dependency>
 		<dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.2-jre</version>
        </dependency>        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

License客户端

硬件识别

linux识别

LinuxCmd.java 通过bash命令得到需要的硬件信息

package cn.test.lic.hardware;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.Arrays;
import java.util.List;

/**
 *
 * 这里使用bash命令操作 dmidecode \ ip 等命令 返回需要的硬件信息
 */
public class LinuxCmd {
   


//    public static void main(String[] args) throws IOException {
   
//        String serialNumber = getSerialNumber();
//        String cpuNumber = getCpuNumber();
//        String mac = getMAC();
//        System.out.println(serialNumber);
//        System.out.println(cpuNumber);
//        System.out.println(mac);
//    }

    /**
     * 获取MAC地址
     * @return 80:61:5f:13:93:29
     * @throws IOException
     */
    public static String getMAC() throws IOException {
   
        //[root@localhost ~]# ip addr show |grep 'link/ether'
        //    link/ether 80:61:5f:13:93:29 brd ff:ff:ff:ff:ff:ff
        //    link/ether 80:61:5f:13:93:2a brd ff:ff:ff:ff:ff:ff
        //    link/ether 52:54:00:d6:1d:db brd ff:ff:ff:ff:ff:ff
        //    link/ether 52:54:00:d6:1d:db brd ff:ff:ff:ff:ff:ff
        //    link/ether 02:42:1b:79:ee:e9 brd ff:ff:ff:ff:ff:ff
        String desc = exec("ip addr show |grep 'link/ether'");
        String[] split = desc.split("\n");
        List<String> list = Arrays.asList(split);
        if (list.size() > 0) {
   
            String s = list.get(0);
            System.out.println(s);
            String[] s1 = s.split(" ");
            String s2 = s1[1];
            System.out.println(s2);
            return s2;
        } else {
   
            return "";
        }
    }


    //-------------------------------------------------------------
    // dmidecode 是linux系统提供的查看cpu相关硬件信息的工具
    //-----------------------------------------

    /**
     * 获取linux的 Cpu ID
     *
     * @return String 11 0F 90 00 FF FB 8B 17
     * @throws IOException
     */
    public static String getCpuNumber() throws IOException {
   
        String desc = exec("dmidecode -t processor | grep 'ID'");
        return handleBashRespStr(desc);
    }

    /**
     * 获取linux 序列号
     *
     * @return String  CD66393F
     * @throws IOException
     */
    public static String getSerialNumber() throws IOException {
   
        String desc = exec("dmidecode | grep 'Serial Number'");
        return handleBashRespStr(desc);
    }




    private static String handleBashRespStr(String desc) {
   
        String[] split = desc.split("\n");
        List<String> list = Arrays.asList(split);
        if (list.size() > 0) {
   
            String s = list.get(0);
            String[] split1 = s.split(":");
            String s1 = split1[1];
            System.err.println(s1);
            return s1;
        } else {
   
            return "";
        }
    }

    /**
     * 执行linux bash命令
     *
     * @param bash 如 ifconfig
     * @return String
     * @throws IOException
     */
    private static String exec(String bash) throws IOException {
   
        String[] cmdA = {
   "/bin/sh", "-c", bash};
        Process process = Runtime.getRuntime().exec(cmdA);
        LineNumberReader br = new LineNumberReader(new InputStreamReader(process.getInputStream()));
        StringBuffer sb = new StringBuffer();
        String line;

        while ((line = br.readLine()) != null) {
   
            System.out.println(line);
            line = line.trim();

            if (line.length() > 0) {
   
                sb.append(line).append("\n");
            }
        }
        return sb.toString();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
windows识别

WmicCmd.java利用cmd命令操作wmic返回需要的硬件信息

package cn.test.lic.hardware;


import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.Arrays;
import java.util.List;

/**
 * wmic是windows系统内置的查看硬件信息的工具
 * 这里利用cmd命令操作wmic返回需要的硬件信息
 */
public class WmicCmd {
   

    private static String execCmd(String cmd) throws IOException {
   

        String[] cmdA = {
   "cmd.exe","/c",cmd};
        Process process = Runtime.getRuntime().exec(cmdA);
        LineNumberReader br = new LineNumberReader(new InputStreamReader(process.getInputStream(),"GBK"));
        StringBuffer sb  = new StringBuffer();
        String line;

        while ((line=br.readLine())!=null){
   
            line = line.trim();
            if (line.length()>0) {
   
                sb.append(line).append("\n");
            }
        }
        return sb.toString();

    }

    private static String handleCmdRespStr(String desc){
   
        String[] split = desc.split("\n");
        List<String> list = Arrays.asList(split);
        if (list.size()>1){
   
            return list.get(1).trim();
        }else {
   
            return "";
        }
    }

    /**
     * 获取mac地址
     * @return String  MACAddress
     * 8C:EC:4B:55:0E:EC
     * 20:41:53:59:4E:FF
     * @throws IOException
     */
    public static String getMacAddress() throws IOException {
   
        final String cmd  = "wmic nicconfig get macaddress";
        String desc = execCmd(cmd);
        return handleCmdRespStr(desc);
    }

    /**
     * 获取cpuId
     * @return String  ProcessorId
     * BFEBFBFF000906E9
     * @throws IOException
     */
    public static String getCpuProcessorId() throws IOException {
   
        final String cmd  = "wmic cpu get processorid";
        String desc = execCmd(cmd);
        return handleCmdRespStr(desc);
    }

    /**
     * 获取bios序列号
     * @return SerialNumber
     *         H34C4N2
     * @throws IOException
     */
    public static String getBiosSerialNumber() throws IOException {
   
        final String cmd  = "wmic bios get serialnumber";
        String desc = execCmd(cmd);
        return handleCmdRespStr(desc);
    }

    /**
     * 获取 主板序列号
     * @return String  SerialNumber
     *                 /H34C4N2/CNWS2007CN02YV/
     * @throws IOException
     */
    public static String getBaseBoardSerialNumber() throws IOException {
   
        final String cmd  = "wmic baseboard get serialnumber";
        String desc = execCmd(cmd);
        return handleCmdRespStr(desc);
    }



}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108

工具类

AES工具类
package cn.test.lic.util;



import cn.hutool.core.codec.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

public class AESjjmUtils {
   


    /**
     * 定义1个默认的aes key
     */
    private static final String DEFAULT_AES_SEAD_KEY = "20230609";

    /**
     * 使用默认key快速加密
     * @param ywStr String 原文
     * @return String
     * @throws Exception
     */
    public static String fastEncrypt(String ywStr) throws Exception {
   
        return encrypt(ywStr,DEFAULT_AES_SEAD_KEY);
    }

    /**
     * 使用默认key快速解密
     * @param mwStr String 密文
     * @return String
     * @throws Exception
     */
    public static String fastDecrypt(String mwStr) throws Exception {
   
        return decrypt(mwStr,DEFAULT_AES_SEAD_KEY);
    }


    /**
     * AES 加密
     * @param ywStr  原文
     * @param aesSeedKey 加密key
     * @return String
     * @throws Exception
     */
    public static String encrypt(String ywStr, String aesSeedKey) throws Exception {
   
        SecretKeySpec spec = getAesSecretKeySpec(aesSeedKey);
        //实例化Cipher
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        //使用密钥初始化,设置为加密模式
        cipher.init(Cipher.ENCRYPT_MODE, spec);
        byte[] byteContent = ywStr.getBytes("utf-8");
        byte[] result = cipher.doFinal(byteContent);
        String aesMw = Base64.encode(result);
        return aesMw;
    }

    /**
     * AES 解密
     * @param mwStr  密文
     * @param aesSeedKey 加密key
     * @return String
     */
    public static String decrypt(String mwStr,String aesSeedKey) throws Exception {
   
        SecretKeySpec spec = getAesSecretKeySpec(aesSeedKey);
        //实例化 Cipher
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        //使用密钥初始化,设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE,spec);
        byte[] decodeBytes = Base64.decode(mwStr);
        byte[] result = cipher.doFinal(decodeBytes);
        String resStr = new String(result, "utf-8");
        return resStr;
    }


    private static SecretKeySpec getAesSecretKeySpec(String aesSeedKey)throws Exception{
   
        //AES 要求密钥长度为 128
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
        random.setSeed(aesSeedKey.getBytes());
        //利用seed值,生成1个128位的key
        KeyGenerator kg = KeyGenerator.getInstance("AES");
        kg.init(128, random);
        //生成一个密钥
        return new SecretKeySpec(kg.generateKey().getEncoded(), "AES");
    }



}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
统一硬件工具类

UniHardwareUtil.java

package cn.test.lic.util;


import cn.test.lic.hardware.LinuxCmd;
import cn.test.lic.hardware.WmicCmd;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

@Slf4j
public class UniHardwareUtil {
   

    public static String getMacAddr() throws IOException {
   
        String property = System.getProperty("os.name");
        if (property.contains("Window")) {
   
            String mac = WmicCmd
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/663841
推荐阅读
相关标签
  

闽ICP备14008679号