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


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

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

идеи?

11 55

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 Duz, другой, похожий на ответ @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 в папке проекта.

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

The 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

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

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

возможно, 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-адреса в качестве идентификатора. Я испытал несколько подводных камней:

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

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

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

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

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

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

использование MAC 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;
      }