JAVA獲取CPUID、主機板序列號、硬碟序列號、MAC地址
阿新 • • 發佈:2019-02-15
最近在修改公司licence程式,需要獲取到更多的硬體唯一標識,以便加密使用。
網上看了很多大神的部落格,思路大概整理了一下,根據系統型別分為兩種方式:
一、windows
通過建立vbs指令碼,然後使用Runtime.getRuntime().exec()執行指令碼,獲取序列號等資訊。
二、LINUX
linux系統其實差不多,同樣使用Runtime.getRuntime().exec()執行linux命令,獲取相關資訊。
程式碼如下:
import java.io.BufferedReader; import java.io.File; import java.io.FileWriter; import java.io.InputStream; import java.io.InputStreamReader; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; public class SerialNumberUtil { /** * 獲取主機板序列號 * @return */ public static String getMotherboardSN() { String result = ""; try { File file = File.createTempFile("realhowto", ".vbs"); file.deleteOnExit(); FileWriter fw = new java.io.FileWriter(file); String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n" + "Set colItems = objWMIService.ExecQuery _ \n" + " (\"Select * from Win32_BaseBoard\") \n" + "For Each objItem in colItems \n" + " Wscript.Echo objItem.SerialNumber \n" + " exit for ' do the first cpu only! \n" + "Next \n"; fw.write(vbs); fw.close(); String path = file.getPath().replace("%20", " "); Process p = Runtime.getRuntime().exec( "cscript //NoLogo " + path); BufferedReader input = new BufferedReader(new InputStreamReader( p.getInputStream())); String line; while ((line = input.readLine()) != null) { result += line; } input.close(); } catch (Exception e) { e.printStackTrace(); } return result.trim(); } /** * 獲取硬碟序列號(該方法獲取的是 碟符的邏輯序列號,並不是硬碟本身的序列號) * 硬碟序列號還在研究中 * @param drive 碟符 * @return */ public static String getHardDiskSN(String drive) { String result = ""; try { File file = File.createTempFile("realhowto", ".vbs"); file.deleteOnExit(); 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"; // see note fw.write(vbs); fw.close(); String path = file.getPath().replace("%20", " "); Process p = Runtime.getRuntime().exec( "cscript //NoLogo " + path); BufferedReader input = new BufferedReader(new InputStreamReader( p.getInputStream())); String line; while ((line = input.readLine()) != null) { result += line; } input.close(); } catch (Exception e) { e.printStackTrace(); } return result.trim(); } /** * 獲取CPU序列號 * @return */ public static String getCPUSerial() { String result = ""; try { File file = File.createTempFile("tmp", ".vbs"); file.deleteOnExit(); FileWriter fw = new java.io.FileWriter(file); String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n" + "Set colItems = objWMIService.ExecQuery _ \n" + " (\"Select * from Win32_Processor\") \n" + "For Each objItem in colItems \n" + " Wscript.Echo objItem.ProcessorId \n" + " exit for ' do the first cpu only! \n" + "Next \n"; // + " exit for \r\n" + "Next"; fw.write(vbs); fw.close(); String path = file.getPath().replace("%20", " "); Process p = Runtime.getRuntime().exec( "cscript //NoLogo " + path); BufferedReader input = new BufferedReader(new InputStreamReader( p.getInputStream())); String line; while ((line = input.readLine()) != null) { result += line; } input.close(); file.delete(); } catch (Exception e) { e.fillInStackTrace(); } if (result.trim().length() < 1 || result == null) { result = "無CPU_ID被讀取"; } return result.trim(); } private static List<String> getLocalHostLANAddress() throws UnknownHostException, SocketException { List<String> ips = new ArrayList<String>(); Enumeration<NetworkInterface> interfs = NetworkInterface.getNetworkInterfaces(); while (interfs.hasMoreElements()) { NetworkInterface interf = interfs.nextElement(); Enumeration<InetAddress> addres = interf.getInetAddresses(); while (addres.hasMoreElements()) { InetAddress in = addres.nextElement(); if (in instanceof Inet4Address) { System.out.println("v4:" + in.getHostAddress()); if(!"127.0.0.1".equals(in.getHostAddress())){ ips.add(in.getHostAddress()); } } } } return ips; } /** * MAC * 通過jdk自帶的方法,先獲取本機所有的ip,然後通過NetworkInterface獲取mac地址 * @return */ public static String getMac() { try { String resultStr = ""; List<String> ls = getLocalHostLANAddress(); for(String str : ls){ InetAddress ia = InetAddress.getByName(str);// 獲取本地IP物件 // 獲得網路介面物件(即網絡卡),並得到mac地址,mac地址存在於一個byte陣列中。 byte[] mac = NetworkInterface.getByInetAddress(ia) .getHardwareAddress(); // 下面程式碼是把mac地址拼裝成String StringBuilder sb = new StringBuilder(); for (int i = 0; i < mac.length; i++) { if (i != 0) { sb.append("-"); } // mac[i] & 0xFF 是為了把byte轉化為正整數 String s = Integer.toHexString(mac[i] & 0xFF); sb.append(s.length() == 1 ? 0 + s : s); } // 把字串所有小寫字母改為大寫成為正規的mac地址並返回 resultStr += sb.toString().toUpperCase()+","; } return resultStr; } catch (Exception ex) { ex.printStackTrace(); } return null; } /***************************linux*********************************/ public static String executeLinuxCmd(String cmd) { try { System.out.println("got cmd job : " + cmd); Runtime run = Runtime.getRuntime(); Process process; process = run.exec(cmd); InputStream in = process.getInputStream(); BufferedReader bs = new BufferedReader(new InputStreamReader(in)); StringBuffer out = new StringBuffer(); byte[] b = new byte[8192]; for (int n; (n = in.read(b)) != -1;) { out.append(new String(b, 0, n)); } in.close(); process.destroy(); return out.toString(); } catch (Exception e) { e.printStackTrace(); } return null; } /** * * @param cmd 命令語句 * @param record 要檢視的欄位 * @param symbol 分隔符 * @return */ public static String getSerialNumber(String cmd ,String record,String symbol) { String execResult = executeLinuxCmd(cmd); String[] infos = execResult.split("\n"); for(String info : infos) { info = info.trim(); if(info.indexOf(record) != -1) { info.replace(" ", ""); String[] sn = info.split(symbol); return sn[1]; } } return null; } /** * 獲取CPUID、硬碟序列號、MAC地址、主機板序列號 * @return */ public static Map<String, String> getAllSn(){ String os = System.getProperty("os.name"); os = os.toUpperCase(); System.out.println(os); Map<String, String> snVo = new HashMap<String, String>(); if("LINUX".equals(os)) { System.out.println("=============>for linux"); String cpuid = getSerialNumber("dmidecode -t processor | grep 'ID'", "ID",":"); System.out.println("cpuid : "+ cpuid); String mainboardNumber = getSerialNumber("dmidecode |grep 'Serial Number'", "Serial Number",":"); System.out.println("mainboardNumber : "+ mainboardNumber); String diskNumber = getSerialNumber("fdisk -l", "Disk identifier",":"); System.out.println("diskNumber : "+ diskNumber); String mac = getSerialNumber("ifconfig -a", "ether"," "); snVo.put("cpuid",cpuid.toUpperCase().replace(" ", "")); snVo.put("diskid",diskNumber.toUpperCase().replace(" ", "")); snVo.put("mac",mac.toUpperCase().replace(" ", "")); snVo.put("mainboard",mainboardNumber.toUpperCase().replace(" ", "")); }else { System.out.println("=============>for windows"); String cpuid = SerialNumberUtil.getCPUSerial(); String mainboard = SerialNumberUtil.getMotherboardSN(); String disk = SerialNumberUtil.getHardDiskSN("c"); String mac = SerialNumberUtil.getMac(); System.out.println("CPU SN:" + cpuid); System.out.println("主機板 SN:" + mainboard); System.out.println("C盤 SN:" + disk); System.out.println("MAC SN:" + mac); snVo.put("cpuid",cpuid.toUpperCase().replace(" ", "")); snVo.put("diskid",disk.toUpperCase().replace(" ", "")); snVo.put("mac",mac.toUpperCase().replace(" ", "")); snVo.put("mainboard",mainboard.toUpperCase().replace(" ", "")); } return snVo; } /** * linux * cpuid : dmidecode -t processor | grep 'ID' * mainboard : dmidecode |grep 'Serial Number' * disk : fdisk -l * mac : ifconfig -a * @param args */ public static void main(String[] args) { getAllSn(); } }
執行結果:
遇到的問題:
一、在放入tomcat中使用時,報錯如下:
原因是我的tomcat路徑:D:\Program Files\tomcat\tomcat-6.0-8180
在專案中讀取時會變成:D:\Program%20Files\tomcat\tomcat-6.0-8180
需要對 %20 進行轉化