如何在Java中获得唯一的计算机标识符(如磁盘ID或主板ID)
我想得到一个独特的计算机与Java,在Windows,MacOS,如果可能的话,Linux的ID。 它可能是一个磁盘UUID,主板s / n …
可以使用Runtime.getRuntime().exec
(它不是一个小程序)。
想法?
使用与网卡关联的MAC地址是常见的。
该地址在Java 6中通过以下API可用:
用于硬件地址的Java 6文档
我没有在Java中使用它,但是对于其他的networking识别应用程序,它是有帮助的。
MAC地址的问题是可能有许多networking适配器连接到计算机。 大多数最新的有两个默认(Wi-Fi +电缆)。 在这种情况下,必须知道应该使用哪个适配器的MAC地址。 我在我的系统上testing了MAC解决scheme,但是我有4个适配器(有线,WiFi,用于虚拟盒的TAP适配器和用于蓝牙的适配器),并且我无法决定应该采用哪个MAC …如果有人决定使用适配器当前正在使用(已分配地址),则会出现新问题,因为有人可以拿起自己的笔记本电脑并从电缆适配器切换到Wi-Fi。 当笔记本通过电缆连接时,存储这种情况下的MAC将无效。
例如那些我在我的系统中find的适配器:
lo MS TCP Loopback interface eth0 Intel(R) Centrino(R) Advanced-N 6205 eth1 Intel(R) 82579LM Gigabit Network Connection eth2 VirtualBox Host-Only Ethernet Adapter eth3 Sterownik serwera dostepu do sieci LAN Bluetooth
我已经用它来列出它们的代码:
Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces(); while (nis.hasMoreElements()) { NetworkInterface ni = nis.nextElement(); System.out.println(ni.getName() + " " + ni.getDisplayName()); }
从这个页面上的选项听,最可以接受的,我在我的解决scheme中使用的是@Ozhan Duz,另一个类似于@finnw答案,他使用JACOB,值得一提的是com4j – 使用WMI的示例可以在这里find :
ISWbemLocator wbemLocator = ClassFactory.createSWbemLocator(); ISWbemServices wbemServices = wbemLocator.connectServer("localhost","Root\\CIMv2","","","","",0,null); ISWbemObjectSet result = wbemServices.execQuery("Select * from Win32_SystemEnclosure","WQL",16,null); for(Com4jObject obj : result) { ISWbemObject wo = obj.queryInterface(ISWbemObject.class); System.out.println(wo.getObjectText_(0)); }
这将打印一些计算机信息连同计算机序列号。 请注意,这个例子所需的所有类都必须由maven-com4j-plugin生成。 maven-com4j-plugin的示例configuration:
<plugin> <groupId>org.jvnet.com4j</groupId> <artifactId>maven-com4j-plugin</artifactId> <version>1.0</version> <configuration> <libId>565783C6-CB41-11D1-8B02-00600806D9B6</libId> <package>win.wmi</package> <outputDirectory>${project.build.directory}/generated-sources/com4j</outputDirectory> </configuration> <executions> <execution> <id>generate-wmi-bridge</id> <goals> <goal>gen</goal> </goals> </execution> </executions> </plugin>
上面的configuration会告诉插件在项目文件夹的target / generated-sources / com4j目录中生成类。
对于那些希望看到即可使用的解决scheme的人,我将包括三个为了在Windows,Linux和Mac OS上获取机器SN而编写的类的链接:
- 在Windows上获得计算机SN的Java代码
- 在Linux上获得计算机SN的Java代码
- 在Mac OS上获得计算机SN的Java代码
作为finnw解决scheme的一种替代方法, wmic命令行实用程序可用于查询设备序列号。 没有外部依赖性,大多数WMI的东西都可以用wmic来build立。
import java.util.Scanner; public class GetBiosSerialNumber { public static void main(String[] args) throws Throwable { // wmic command for diskdrive id: wmic DISKDRIVE GET SerialNumber // wmic command for cpu id : wmic cpu get ProcessorId Process process = Runtime.getRuntime().exec(new String[] { "wmic", "bios", "get", "serialnumber" }); process.getOutputStream().close(); Scanner sc = new Scanner(process.getInputStream()); String property = sc.next(); String serial = sc.next(); System.out.println(property + ": " + serial); } }
OSHI
项目提供与平台无关的硬件工具。
Maven依赖:
<dependency> <groupId>com.github.dblock</groupId> <artifactId>oshi-core</artifactId> <version>LATEST</version> </dependency>
例如,您可以使用类似下面的代码来唯一标识一台机器:
import oshi.SystemInfo; import oshi.hardware.CentralProcessor; import oshi.hardware.HardwareAbstractionLayer; import oshi.software.os.OperatingSystem; public class ComputerIdentifier { public static String generateLicenseKey() throws Exception { SystemInfo systemInfo = new SystemInfo(); OperatingSystem operatingSystem = systemInfo.getOperatingSystem(); HardwareAbstractionLayer hardwareAbstractionLayer = systemInfo.getHardware(); CentralProcessor centralProcessor = hardwareAbstractionLayer.getProcessor(); String vendor = operatingSystem.getManufacturer(); String processorSerialNumber = centralProcessor.getSystemSerialNumber(); String processorIdentifier = centralProcessor.getIdentifier(); int processors = centralProcessor.getLogicalProcessorCount(); String delimiter = "#"; return vendor + delimiter + processorSerialNumber + delimiter + processorIdentifier + delimiter + processors; } public static void main(String[] arguments) throws Exception { String identifier = generateLicenseKey(); System.out.println(identifier); } }
我的机器的输出:
Microsoft#57YRD12#Intel64 Family 6 Model 60 Stepping 3#8
由于至less处理器序列号会有所不同,因此您的输出将有所不同。
你想用这个独特的ID做什么? 也许你可以在没有这个ID的情况下做你想做的事。
MAC地址可能是一个选项,但这不是可信的唯一ID,因为用户可以更改计算机的MAC地址。
要获得主板或处理器ID检查这个链接 。
仅在Windows上,您可以使用WMI通过COM桥(如JACOB)获取主板ID。
例:
import java.util.Enumeration; import com.jacob.activeX.ActiveXComponent; import com.jacob.com.ComThread; import com.jacob.com.EnumVariant; import com.jacob.com.Variant; public class Test { public static void main(String[] args) { ComThread.InitMTA(); try { ActiveXComponent wmi = new ActiveXComponent("winmgmts:\\\\."); Variant instances = wmi.invoke("InstancesOf", "Win32_BaseBoard"); Enumeration<Variant> en = new EnumVariant(instances.getDispatch()); while (en.hasMoreElements()) { ActiveXComponent bb = new ActiveXComponent(en.nextElement().getDispatch()); System.out.println(bb.getPropertyAsString("SerialNumber")); break; } } finally { ComThread.Release(); } } }
如果您select使用MAC地址来标识机器,则可以使用WMI来确定是否通过USB连接接口(如果您想排除USB适配器)。
也可以通过WMI获得硬盘ID,但这是不可靠的。
使用MAC地址作为标识符时要小心。 我遇到过几个问题:
- 在OS X上,不处于活动状态的以太网端口不会显示在NetworkInterface.getNetworkInterfaces()枚举中。
- 如果您拥有适当的操作系统权限,则更改卡上的MAC地址非常容易。
- Java有一个不正确识别“虚拟”接口的习惯。 即使使用NetworkInterface.isVirtual()也不会总是告诉你事实。
即使有上述问题,我仍然认为这是硬件locking许可证的最好的纯Java方法。
不知道你的所有要求。 例如,您是否试图从世界上所有计算机中唯一标识一台计算机,或者您是否试图从应用程序的一组用户中唯一标识一台计算机。 另外,你可以在系统上创build文件吗?
如果你能够创build一个文件。 您可以创build一个文件,并使用该文件的创build时间作为唯一的ID。 如果你在用户空间创build它,那么它将在特定的机器上唯一标识你的应用程序的用户。 如果你在全球某个地方创build了它,那么它可以唯一标识该机器。
再次,大多数情况下,速度有多快是足够快,或在这种情况下,多么独特是足够的独特。
我想你应该看看这个链接 …你可以使用多个标识符,如MAC + OS +主机名+ CPU ID + 主板序列号混合键。
如果任务是关于logging系统的唯一ID,则使用MAC ID是最简单的方式。
mac id的改变尽pipe是可能的,即使系统的其他id的改变也是可能的,即相应的设备被replace。
所以,除非需要一个唯一的ID是不知道的,否则我们可能无法find合适的解决scheme。
但是,下面的链接有助于解压缩mac地址。 http://www.stratos.me/2008/07/find-mac-address-using-java/
在我写的发布的Java程序中,我使用了主板的序列号(这是我使用的窗口); 然而,这只适用于Windows,因为我的函数创build一个临时的VB脚本,它使用WMI来检索值。
public static String getMotherboardSerial() { String result = ""; try { File file = File.createTempFile("GetMBSerial",".vbs"); file.deleteOnExit(); FileWriter fw = new FileWriter(file); String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n" + "Set colItems = objWMIService.ExecQuery _ \n" + " (\"Select * from Win32_ComputerSystemProduct\") \n" + "For Each objItem in colItems \n" + " Wscript.Echo objItem.IdentifyingNumber \n" + "Next \n"; fw.write(vbs); fw.close(); Process gWMI = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath()); BufferedReader input = new BufferedReader(new InputStreamReader(gWMI.getInputStream())); String line; while ((line = input.readLine()) != null) { result += line; System.out.println(line); } input.close(); } catch(Exception e){ e.printStackTrace(); } result = result.trim(); return result; }
用于唯一标识Windows机器。 确保当你使用wmic有一个替代方法的策略。 由于“wmic bios获得serialnumber”可能无法在所有机器上工作,您可能需要有其他方法:
# Get serial number from bios wmic bios get serialnumber # If previous fails, get UUID wmic csproduct get UUID # If previous fails, get diskdrive serialnumber wmic DISKDRIVE get SerialNumber
资源:唯一识别Windows机器的最佳途径http://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine/