Как получить уникальный идентификатор компьютера в Java (например, идентификатор диска или идентификатор материнской платы)?

Я хотел бы получить идентификатор, уникальный для компьютера с Java, на Windows, MacOS и, если возможно, Linux. Это может быть UUID диска, материнская плата S / N...

Runtime.getRuntime().exec может использоваться (это не апплет).

идеи?

11 ответов


обычно используется MAC-адрес, связанный с сетевой картой.

адрес доступен в Java 6 через следующий API:

Java 6 Docs для аппаратного адреса

Я не использовал его в Java, но для других приложений сетевой идентификации это было полезно.


проблема с MAC-адресом заключается в том, что к компьютеру может быть подключено множество сетевых адаптеров. Большинство новейших имеют по умолчанию два (wi-fi + кабель). В такой ситуации нужно было бы знать, какой MAC-адрес адаптера следует использовать. Я тестировал решение MAC в своей системе, но у меня есть 4 адаптера (кабель, WiFi, адаптер для виртуальной коробки и один для Bluetooth), и я не смог решить, какой 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

код, который я использовал для их перечисления:

Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
while (nis.hasMoreElements()) {
    NetworkInterface ni = nis.nextElement();
    System.out.println(ni.getName() + " " + ni.getDisplayName());
}

из вариантов слушайте на этой странице, наиболее приемлемым для меня, и тот, который я использовал в своем решении, - это @Ozhan ДУЗ, другой, похож на ответ @finnw, где он использовал Джейкоба, и стоит упомянуть 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));
}

это напечатает некоторую информацию о компьютере вместе с серийным номером компьютера. Обратите внимание, что все классы, требуемые этим примером, должны быть сгенерированы 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 в папке проекта.

для тех, кто хотел бы видеть готовые решение, я включаю ссылки на три класса, которые я написал, чтобы получить машину SN на Windows, Linux и Mac OS:


на 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

ваш выход будет отличаться, так как по крайней мере серийный номер процессора будет отличаться.


Что вы хотите сделать с этим уникальным идентификатором? Может, ты сможешь делать, что захочешь без этого удостоверения.

возможно, MAC-адрес является одним из вариантов, но это не надежный уникальный идентификатор, потому что пользователь может изменить MAC-адрес компьютера.

чтобы получить идентификатор материнской платы или процессора, проверьте это ссылке.


только в Windows вы можете получить идентификатор материнской платы с помощью WMI, через мост COM, такой как Яков.

пример:

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, но это ненадежно.


будьте осторожны при использовании MAC-адреса в качестве идентификатора. Я испытал несколько gotchas:

  1. в OS X порты ethernet, которые не активны / не отображаются в NetworkInterface.getNetworkInterfaces() перечисление.
  2. Это безумно легко изменить MAC-адрес карты, если у вас есть соответствующие привилегии ОС.
  3. Java имеет привычку неправильно идентифицировать "виртуальные" интерфейсы. Даже используя NetworkInterface.свойство isvirtual() не всегда будет говорить вам правду.

даже с вышеуказанными проблемами, я все еще думаю, что это лучший чистый подход Java к аппаратной блокировке лицензии.


Не зная всех ваших требований. Например, вы пытаетесь однозначно идентифицировать компьютер из всех компьютеров в мире или просто пытаетесь однозначно идентифицировать компьютер из набора пользователей вашего приложения. Кроме того, вы можете создавать файлы в системе?

Если вы можете создать файл. Вы можете создать файл и использовать время создания файла в качестве уникального идентификатора. Если вы создадите его в пользовательском пространстве, он однозначно идентифицирует пользователя вашего применение на определенной машине. Если вы создали его где-то в глобальном масштабе, он может однозначно идентифицировать машину.

опять же, как и большинство вещей, как быстро достаточно быстро.. или в данном случае, насколько уникален, настолько уникален.


Я думаю, вы должны посмотреть на это ссылке ... вы можете сделать смешанный ключ, используя несколько идентификаторы, такие как mac+os+hostname+идентификатор процессора+серийный номер материнской платы.


использование MAC id наиболее простой способ, если задача заключается в регистрации уникального id системы.

изменение MAC id, хотя это возможно, даже изменение других идентификаторов системы также возможно, что соответствующее устройство заменяется.

Итак, если не известно, что требуется для уникального идентификатора, мы не сможем найти подходящее решение.

однако приведенная ниже ссылка полезна для извлечения mac адреса. http://www.stratos.me/2008/07/find-mac-address-using-java/


для уникальной идентификации машины 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/


в программах 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;
      }