如何在 Java 中获取唯一的计算机标识符(如磁盘 ID 或主板 ID)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1986732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get a unique computer identifier in Java (like disk ID or motherboard ID)?
提问by Gohu
I'd like to get an id unique to a computer with Java, on Windows, MacOS and, if possible, Linux. It could be a disk UUID, motherboard S/N...
我想在 Windows、MacOS 和 Linux(如果可能)上使用 Java 获得唯一的计算机 ID。它可能是磁盘 UUID、主板 S/N...
Runtime.getRuntime().exec
can be used (it is not an applet).
Runtime.getRuntime().exec
可以使用(它不是小程序)。
Ideas?
想法?
采纳答案by nickk_can
It is common to use the MAC address is associated with the network card.
通常使用与网卡相关联的 MAC 地址。
The address is available in Java 6 through through the following API:
该地址可通过以下 API 在 Java 6 中获得:
Java 6 Docs for Hardware Address
I haven't used it in Java, but for other network identification applications it has been helpful.
我没有在 Java 中使用过它,但是对于其他网络识别应用程序,它很有帮助。
回答by Pedro Ghilardi
What do you want to do with this unique ID? Maybe you can do what you want without this ID.
你想用这个唯一 ID 做什么?也许没有这个ID你可以为所欲为。
The MAC address maybe is one option but this is not an trusted unique ID because the user can change the MAC address of a computer.
MAC 地址可能是一种选择,但这不是可信的唯一 ID,因为用户可以更改计算机的 MAC 地址。
To get the motherboard or processor ID check on this link.
要在此链接上检查主板或处理器 ID 。
回答by Michel Gokan
回答by finnw
On Windows only, you can get the motherboard ID using WMI, through a COM bridge such as JACOB.
仅在 Windows 上,您可以使用WMI通过 COM 桥接器(例如JACOB )获取主板 ID 。
Example:
例子:
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();
}
}
}
And if you choose to use the MAC address to identify the machine, you can use WMI to determine whether an interface is connected via USB (if you want to exclude USB adapters.)
而如果你选择使用MAC地址来识别机器,你可以使用WMI来确定一个接口是否通过USB连接(如果你想排除USB适配器。)
It's also possible to get a hard drive ID via WMI but this is unreliable.
也可以通过 WMI 获取硬盘驱动器 ID,但这是不可靠的。
回答by Jason Nichols
Be careful when using the MAC address as an identifier. I've experienced several gotchas:
使用 MAC 地址作为标识符时要小心。我经历了几个陷阱:
- On OS X, ethernet ports that are not active/up do not show up in the NetworkInterface.getNetworkInterfaces()Enumeration.
- It's insanely easy to change a MAC address on cards if you've got appropriate OS privileges.
- Java has a habit of not correctly identifying "virtual" interfaces. Even using the NetworkInterface.isVirtual()won't always tell you the truth.
- 在 OS X 上,非活动/启动的以太网端口不会显示在NetworkInterface.getNetworkInterfaces()枚举中。
- 如果您有适当的操作系统权限,更改卡上的 MAC 地址非常容易。
- Java 有不能正确识别“虚拟”接口的习惯。即使使用NetworkInterface.isVirtual()也不总是告诉你真相。
Even with the above issues, I still think it's the best pure Java approach to hardware locking a license.
即使存在上述问题,我仍然认为这是硬件锁定许可证的最佳纯 Java 方法。
回答by sindri
Not Knowing all of your requirements. For example, are you trying to uniquely identify a computer from all of the computers in the world, or are you just trying to uniquely identify a computer from a set of users of your application. Also, can you create files on the system?
不知道您的所有要求。例如,您是想从世界上的所有计算机中唯一标识一台计算机,还是只是想从应用程序的一组用户中唯一标识一台计算机。另外,你可以在系统上创建文件吗?
If you are able to create a file. You could create a file and use the creation time of the file as your unique id. If you create it in user space then it would uniquely identify a user of your application on a particular machine. If you created it somewhere global then it could uniquely identify the machine.
如果您能够创建文件。您可以创建一个文件并使用该文件的创建时间作为您的唯一 ID。如果您在用户空间中创建它,那么它将在特定机器上唯一标识您的应用程序的用户。如果您在全局某个地方创建它,那么它可以唯一地标识机器。
Again, as most things, How fast is fast enough.. or in this case, how unique is unique enough.
同样,与大多数事情一样,多快就足够快了……或者在这种情况下,有多独特就足够独特。
回答by Vamsy
The usage of MACid is most easier way if the task is about logging the unique id a system.
如果任务是关于记录系统的唯一 id ,则使用MACid 是最简单的方法。
the change of mac id is though possible, even the change of other ids of a system are also possible is that respective device is replaced.
mac id 的改变是可能的,即使是一个系统的其他 id 的改变也是可能的,只是相应的设备被替换了。
so, unless what for a unique id is required is not known, we may not be able to find an appropriate solution.
因此,除非不知道需要什么唯一 id,否则我们可能无法找到合适的解决方案。
However, the below link is helpful extracting mac addresses. http://www.stratos.me/2008/07/find-mac-address-using-java/
但是,以下链接有助于提取 mac 地址。 http://www.stratos.me/2008/07/find-mac-address-using-java/
回答by Bartosz Firyn
The problem with MAC address is that there can be many network adapters connected to the computer. Most of the newest ones have two by default (wi-fi + cable). In such situation one would have to know which adapter's MAC address should be used. I tested MAC solution on my system, but I have 4 adapters (cable, WiFi, TAP adapter for Virtual Box and one for Bluetooth) and I was not able to decide which MAC I should take... If one would decide to use adapter which is currently in use (has addresses assigned) then new problem appears since someone can take his/her laptop and switch from cable adapter to wi-fi. With such condition MAC stored when laptop was connected through cable will now be invalid.
MAC 地址的问题是可以有许多网络适配器连接到计算机。大多数最新的默认情况下有两个(wi-fi +电缆)。在这种情况下,人们必须知道应该使用哪个适配器的 MAC 地址。我在我的系统上测试了 MAC 解决方案,但我有 4 个适配器(用于 Virtual Box 的电缆、WiFi、TAP 适配器和一个用于蓝牙的适配器)并且我无法决定我应该使用哪个 MAC...如果有人决定使用适配器当前正在使用(已分配地址)然后出现新问题,因为有人可以带着他/她的笔记本电脑并从电缆适配器切换到 Wi-Fi。有了这样的条件,当笔记本电脑通过电缆连接时存储的 MAC 现在将无效。
For example those are adapters I found in my system:
例如,这些是我在系统中找到的适配器:
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
Code I've used to list them:
我用来列出它们的代码:
Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
while (nis.hasMoreElements()) {
NetworkInterface ni = nis.nextElement();
System.out.println(ni.getName() + " " + ni.getDisplayName());
}
From the options listen on this page, the most acceptable for me, and the one I've used in my solution is the one by @Ozhan Duz, the other one, similar to @finnw answer where he used JACOB, and worth mentioning is com4j- sample which makes use of WMI is available here:
从这个页面上的选项收听,对我来说最能接受的,我在我的解决方案中使用的是@Ozhan Duz 的一个,另一个类似于@finnw 回答,他使用了 JACOB,值得一提的是com4j- 使用 WMI 的示例可在此处获得:
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));
}
This will print some computer information together with computer Serial Number. Please note that all classes required by this example has to be generated by maven-com4j-plugin. Example configuration for maven-com4j-plugin:
这将打印一些计算机信息和计算机序列号。请注意,此示例所需的所有类都必须由 maven-com4j-plugin 生成。maven-com4j-plugin 的示例配置:
<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>
Above's configuration will tell plugin to generate classes in target/generated-sources/com4j directory in the project folder.
上面的配置会告诉插件在项目文件夹的 target/generated-sources/com4j 目录中生成类。
For those who would like to see ready-to-usesolution, I'm including links to the three classes I wrote to get machine SN on Windows, Linux and Mac OS:
对于那些希望看到即用型解决方案的人,我提供了指向我编写的三个类的链接,这些类用于在 Windows、Linux 和 Mac OS 上获取机器 SN:
回答by Charles Eddy
In the java programs I have written for release I used the motherboard serial number (which is what I beleive windows use); however, this only works on windows as my function creates a temporary VB script which uses the WMI to retrieve the value.
在我为发布而编写的 java 程序中,我使用了主板序列号(这是我相信 Windows 使用的);但是,这仅适用于 Windows,因为我的函数创建了一个临时 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;
}
回答by Basil Musa
For identifying a windows machine uniquely. Make sure when you use wmic to have a strategy of alternative methods. Since "wmic bios get serialnumber" might not work on all machines, you might need to have additional methods:
用于唯一标识 Windows 机器。确保在使用 wmic 时具有替代方法的策略。由于“wmic bios get 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
Resources: The Best Way To Uniquely Identify A Windows Machine http://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine/
资源:唯一标识 Windows 计算机的最佳方法 http://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine/