首页 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
俄罗斯方块
↓俄罗斯方块↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
资讯 业界资讯 软件杂谈 编程开发 网站建设 网络观查 搜索引擎 移动应用 网站运营 网络地图
开发 移动开发 Web前端 架构设计 编程语言 互联网 数据库 系统运维 云计算 开发杂谈
[架构设计] APDPlat中的机器码生成机制
APDPlat中的机器码生成机制

APDPlat提供了机器绑定的功能,对于不同的机器会生成不同的机器码,必须要对生成的机器码进行计算获得注册码,注册码验证成功之后系统才能正常运行。
 
本文主要介绍APDPlat如何生成机器码。
 
首先,定义了一个统一的接口,以支持不同操作系统不同实现的透明切换:
 
/**
 *生成机器码的接口,不同平台有不同实现
 * @author 杨尚川
 */
public interface SequenceService {
    /**
     * 获取机器码
     * @return  机器码
     */
    public String getSequence();    
}

 
 
其次,定义了一个抽象类,实现了一些通用的功能,如生成MD5摘要将很长的字符串以固定的位数分割开,以便于人类阅读(如将机器码 71F5DA7F495E7F706D47F3E63DC6349A 每4个一组,以-分割为71F5-DA7F-495E-7F70-6D47-F3E6-3DC6-349A)、利用sigar来生成机器码。这里需要在pom.xml中加入sigar依赖。
 
<dependency>
	<groupId>org.fusesource</groupId>
	<artifactId>sigar</artifactId>
	<version>1.6.4</version>
	<exclusions>
		<exclusion>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
		</exclusion>
	</exclusions>
</dependency>

 
 
import org.apdplat.module.system.service.PropertyHolder;
import org.apdplat.platform.log.APDPlatLogger;
import org.apdplat.platform.util.ConvertUtils;
import org.apdplat.platform.util.FileUtils;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import org.apdplat.platform.log.APDPlatLoggerFactory;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.NetFlags;
import org.hyperic.sigar.NetInterfaceConfig;
import org.hyperic.sigar.Sigar;

/**
 *机器码生成的通用服务
 * @author 杨尚川
 */
public abstract class AbstractSequenceService   implements SequenceService{
    protected final APDPlatLogger LOG = APDPlatLoggerFactory.getAPDPlatLogger(getClass());
    /**
     * 对一段String生成MD5摘要信息
     * @param message 要摘要的String
     * @return 生成的MD5摘要信息
     */
    protected String getMD5(String message) {
        message += "{apdplat}";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            LOG.debug("MD5摘要长度:" + md.getDigestLength());
            byte[] b = md.digest(message.getBytes("utf-8"));
            String md5 = ConvertUtils.byte2HexString(b)+message.length();
            return getSplitString(md5);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            LOG.error("MD5摘要失败",e);
        }
        return null;
    }
    /**
     * 将很长的字符串以固定的位数分割开,以便于人类阅读
     * @param str
     * @return 
     */
    protected String getSplitString(String str){ 
        return getSplitString(str, "-", 4);
    }
    /**
     * 将很长的字符串以固定的位数分割开,以便于人类阅读
     * 如将
     * 71F5DA7F495E7F706D47F3E63DC6349A
     * 以-,每4个一组,则分割为
     * 71F5-DA7F-495E-7F70-6D47-F3E6-3DC6-349A
     * @param str 字符串
     * @param split 分隔符
     * @param length 长度
     * @return 
     */
    protected 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;
    }    
    /**
     * 利用sigar来生成机器码,当然这个实现不是很好,无法获得CPU ID,希望有兴趣的朋友来改进这个实现
     * @param osName 操作系统类型
     * @return 机器码
     */
    protected String getSigarSequence(String osName) {
        try {
            File libFile = new File(FileUtils.getAbsolutePath("/WEB-INF/lib/"+PropertyHolder.getProperty("libsigar."+osName)));
            LOG.debug("libsigar."+osName+" : "+libFile.getAbsolutePath());
            
            System.load(libFile.getAbsolutePath());
            Set<String> result = new HashSet<>();
            Sigar sigar = new Sigar();
            String[] ifaces = sigar.getNetInterfaceList();
            for (String iface : ifaces) {
                NetInterfaceConfig cfg = sigar.getNetInterfaceConfig(iface);                if (NetFlags.LOOPBACK_ADDRESS.equals(cfg.getAddress()) || (cfg.getFlags() & NetFlags.IFF_LOOPBACK) != 0
                        || NetFlags.NULL_HWADDR.equals(cfg.getHwaddr())) {
                    continue;
                }
                String mac = cfg.getHwaddr();
                result.add(mac);
                LOG.debug("mac: " + mac);
            }
            if(result.size()<1){
                return null;
            }
            Properties props = System.getProperties();
            String javaVersion = props.getProperty("java.version");
            result.add(javaVersion);
            LOG.debug("Java的运行环境版本:    " + javaVersion);
            String javaVMVersion = props.getProperty("java.vm.version");
            result.add(javaVMVersion);
            LOG.debug("Java的虚拟机实现版本:    " + props.getProperty("java.vm.version"));
            String osVersion = props.getProperty("os.version");
            result.add(osVersion);
            LOG.debug("操作系统的版本:    " + props.getProperty("os.version"));

            Mem mem = sigar.getMem();
            // 内存总量
            String totalMem = mem.getTotal() / 1024L + "K av";
            LOG.debug("内存总量:    " + totalMem);
            result.add(totalMem);

            LOG.debug("result:    " + result);
            String machineCode = getMD5(result.toString());

            return machineCode;
        } catch (Throwable ex) {
            LOG.error("生成 "+osName+" 平台下的机器码失败", ex);
        }
        return null;
    }
}

 
 
最后,我们分别看看不同平台的实现。
 
Windows:
 
/**
 *在Windows平台上生成机器码
 * @author 杨尚川
 */
public final class WindowsSequenceService extends AbstractSequenceService{    
    @Override
    public String getSequence() {        
        String cpuID=getCPUSerial();
        String hdID=getHDSerial("C");
        if(cpuID==null || hdID==null){
            return null;
        }
        String machineCode = getMD5(cpuID+hdID);
                
        return machineCode;
    }
    
    /**
     *
     * @param drive 硬盘驱动器分区 如C,D
     * @return 该分区的卷标
     */
    private String getHDSerial(String drive) {
        StringBuilder result = new StringBuilder();
        try {
            File file = File.createTempFile("tmp", ".vbs");
            file.deleteOnExit();
            try (FileWriter fw = new java.io.FileWriter(file)) {
                String vbs = "Set objFSO = CreateObject(\"Scripting.FileSystemObject\")\n"
                        + "Set colDrives = objFSO.Drives\n" + "Set objDrive = colDrives.item(\"" + drive + "\")\n"
                        + "Wscript.Echo objDrive.SerialNumber";
                fw.write(vbs);
            }
            Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
            try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
                String line;
                while ((line = input.readLine()) != null) {
                    result.append(line);
                }
            }
            file.delete();
        } catch (Throwable e) {
            LOG.error("生成HDSerial失败", e);
        }
        if (result.length() < 1) {
            LOG.info("无磁盘ID被读取");
        }

        return result.toString();
    }

    /**
     * 获取CPU号,多CPU时,只取第一个
     * @return
     */
    private String getCPUSerial() {
        StringBuilder result = new StringBuilder();
        try {
            File file = File.createTempFile("tmp", ".vbs");
            file.deleteOnExit();
            try (FileWriter fw = new FileWriter(file)) {
                String vbs = "On Error Resume Next \r\n\r\n" + "strComputer = \".\"  \r\n"
                        + "Set objWMIService = GetObject(\"winmgmts:\" _ \r\n"
                        + "    & \"{impersonationLevel=impersonate}!\\\\\" & strComputer & \"\\root\\cimv2\") \r\n"
                        + "Set colItems = objWMIService.ExecQuery(\"Select * from Win32_Processor\")  \r\n "
                        + "For Each objItem in colItems\r\n " + "    Wscript.Echo objItem.ProcessorId  \r\n "
                        + "    exit for  ' do the first cpu only! \r\n" + "Next                    ";

                fw.write(vbs);
            }
            Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
            try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
                String line;
                while ((line = input.readLine()) != null) {
                    result.append(line);
                }
            }
            file.delete();
        } catch (Throwable e) {
            LOG.error("生成CPUSerial失败", e);
        }
        if (result.length() < 1) {
            LOG.info("无CPU_ID被读取");
        }
        return result.toString();
    }
    
    public static void main(String[] args) {        
        SequenceService s = new WindowsSequenceService();
        String seq = s.getSequence();
        System.out.println(seq);
    }
}

 
 
Linux:
 
/**
 *在Linux平台上生成机器码
 * @author 杨尚川
 */
public class LinuxSequenceService  extends AbstractSequenceService{
    @Override
    public String getSequence() {
        return getSigarSequence("linux");
    }

    public static void main(String[] args) {
        SequenceService s = new LinuxSequenceService();
        String seq = s.getSequence();
        System.out.println(seq);
    }
}

 
 
Mac OS X:
 
/**
 *在Mac OS X平台上生成机器码
 * @author 杨尚川
 */
public class MacSequenceService    extends AbstractSequenceService{
    @Override
    public String getSequence() {
        return getSigarSequence("mac");
    }
   
    public static void main(String[] args) {
        SequenceService s = new MacSequenceService();
        String seq = s.getSequence();
        System.out.println(seq);
    }
}

 
 
Solaris:
 
/**
 *在Solaris平台上生成机器码
 * @author 杨尚川
 */
public class SolarisSequenceService    extends AbstractSequenceService{
    @Override
    public String getSequence() {
        return getSigarSequence("solaris");
    }

    public static void main(String[] args) {
        SequenceService s = new SolarisSequenceService();
        String seq = s.getSequence();
        System.out.println(seq);
    }    
}

 
 
 
 APDPlat托管在Github
更多


 此文从网络中自动搜索生成,不代表本网站赞成被搜索网站的内容或立场    查看原文
 
  网站联系 软件世界网-www.sjsjw.com ©2014 蜀ICP备06016416号 三峰网旗下网站