我希望在Windows,MacOS以及Linux(如果可能的话)上获得一台带有Java的计算机的唯一ID。它可能是磁盘UUID,主板S / N ......
可以使用 Runtime.getRuntime().exec
(它不是applet)。
想法?
答案 0 :(得分:43)
MAC地址的问题是可以有许多网络适配器连接到计算机。大多数最新版本默认有两个(wi-fi + cable)。在这种情况下,人们必须知道应该使用哪个适配器的MAC地址。我在我的系统上测试了MAC解决方案,但是我有4个适配器(有线,WiFi,用于Virtual Box的TAP适配器和一个用于蓝牙),我无法确定应该采用哪个MAC ...如果有人决定使用适配器当前正在使用(已分配地址)然后出现新问题,因为有人可以带他/她的笔记本电脑并从电缆适配器切换到Wi-Fi。当笔记本电脑通过电缆连接时存储的MAC条件现在无效。
例如,那些是我在我的系统中找到的适配器:
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
代码I用于列出它们:
Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
while (nis.hasMoreElements()) {
NetworkInterface ni = nis.nextElement();
System.out.println(ni.getName() + " " + ni.getDisplayName());
}
从这个页面上的选项听取,对我来说最容易接受的,我在我的解决方案中使用的那个是@Ozhan Duz,另一个,类似于@finnw回答,他使用了JACOB ,值得一提的是com4j - 可以使用WMI的样本here:
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的配置示例:
<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>
上面的配置会告诉插件在项目文件夹的target / generated-sources / com4j目录中生成类。
对于那些希望看到即用型解决方案的人,我包括我在Windows,Linux和Mac OS上为了获取机器SN所编写的三个类的链接: / p>
答案 1 :(得分:24)
OSHI
项目提供与平台无关的硬件实用程序。
Maven依赖:
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>LATEST</version>
</dependency>
例如,您可以使用类似以下代码的内容来唯一标识计算机:
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.ComputerSystem;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.OperatingSystem;
class ComputerIdentifier
{
static String generateLicenseKey()
{
SystemInfo systemInfo = new SystemInfo();
OperatingSystem operatingSystem = systemInfo.getOperatingSystem();
HardwareAbstractionLayer hardwareAbstractionLayer = systemInfo.getHardware();
CentralProcessor centralProcessor = hardwareAbstractionLayer.getProcessor();
ComputerSystem computerSystem = hardwareAbstractionLayer.getComputerSystem();
String vendor = operatingSystem.getManufacturer();
String processorSerialNumber = computerSystem.getSerialNumber();
String processorIdentifier = centralProcessor.getIdentifier();
int processors = centralProcessor.getLogicalProcessorCount();
String delimiter = "#";
return vendor +
delimiter +
processorSerialNumber +
delimiter +
processorIdentifier +
delimiter +
processors;
}
public static void main(String[] arguments)
{
String identifier = generateLicenseKey();
System.out.println(identifier);
}
}
我机器的输出:
Microsoft#57YRD12#Intel64 Family 6 Model 60 Stepping 3#8
您的输出会有所不同,因为至少处理器序列号会有所不同。
答案 2 :(得分:19)
通常使用与网卡关联的MAC地址。
该地址在Java 6中通过以下API提供:
Java 6 Docs for Hardware Address
我没有在Java中使用它,但对于其他网络识别应用程序,它一直很有帮助。
答案 3 :(得分:12)
答案 4 :(得分:9)
仅在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();
}
}
}
如果您选择使用MAC地址来识别机器,您可以使用WMI来确定接口是否通过USB连接(如果您要排除USB适配器。)
也可以通过WMI获取硬盘ID,但这是不可靠的。
答案 5 :(得分:7)
使用MAC地址作为标识符时要小心。我经历了几次陷阱:
即使遇到上述问题,我仍然认为这是硬件锁定许可证的最佳纯Java方法。
答案 6 :(得分:6)
不了解您的所有要求。例如,您是尝试从世界上所有计算机中唯一标识计算机,还是只是尝试从应用程序的一组用户中唯一标识计算机。另外,您可以在系统上创建文件吗?
如果您能够创建文件。您可以创建一个文件,并使用该文件的创建时间作为您的唯一ID。如果您在用户空间中创建它,那么它将唯一地标识特定计算机上的应用程序的用户。如果您在某个全局创建它,那么它可以唯一地识别该机器。
同样,大多数情况下,速度有多快......或者在这种情况下,独特性是多么独特。
答案 7 :(得分:3)
我认为你应该看看这个link ...你可以使用几个来制作一个混合密钥 标识符,例如mac + os + hostname + cpu id + motherboard serial number。
答案 8 :(得分:1)
如果任务是关于将唯一ID记录为系统,则使用 MAC id是最简单的方法。
虽然可以改变mac id,但即使系统的其他ID的更改也可以替换相应的设备。
所以,除非需要针对唯一ID的内容,否则我们可能无法找到合适的解决方案。
但是,以下链接有助于解压缩mac地址。 http://www.stratos.me/2008/07/find-mac-address-using-java/
答案 9 :(得分:1)
用于唯一识别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
资源: 唯一识别Windows机器的最佳方法 http://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine/
答案 10 :(得分:0)
在我为发布而编写的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;
}