web-dev-qa-db-fra.com

Comment obtenir un identifiant d'ordinateur unique dans Java (comme l'ID de disque ou l'ID de carte mère)?

J'aimerais obtenir un identifiant unique pour un ordinateur avec Java, sur Windows, MacOS et, si possible, Linux. Il peut s'agir d'un disque UUID, d'une carte mère S/N ...

Runtime.getRuntime().exec peut être utilisé (ce n'est pas une applet).

Des idées?

57
Gohu

Il est courant d'utiliser l'adresse MAC associée à la carte réseau.

L'adresse est disponible en Java 6 via l'API suivante:

Java 6 Docs for Hardware Address

Je ne l'ai pas utilisé en Java, mais pour d'autres applications d'identification de réseau, cela a été utile.

19
nickk_can

Le problème avec l'adresse MAC est qu'il peut y avoir de nombreuses cartes réseau connectées à l'ordinateur. La plupart des plus récents en ont deux par défaut (wi-fi + câble). Dans une telle situation, il faudrait savoir quelle adresse MAC de l'adaptateur doit être utilisée. J'ai testé la solution MAC sur mon système, mais j'ai 4 adaptateurs (câble, WiFi, adaptateur TAP pour Virtual Box et un pour Bluetooth) et je n'ai pas pu décider quel MAC je devrais prendre ... Si l'on décidait d'utiliser l'adaptateur qui est actuellement en cours d'utilisation (a des adresses attribuées), puis un nouveau problème apparaît car quelqu'un peut prendre son ordinateur portable et passer de l'adaptateur de câble au wi-fi. Avec une telle condition, le MAC stocké lorsque l'ordinateur portable était connecté via un câble ne sera plus valide.

Par exemple, ce sont des adaptateurs que j'ai trouvés dans mon système:

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 que j'ai utilisé pour les répertorier:

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

Parmi les options d'écoute sur cette page, la plus acceptable pour moi, et celle que j'ai utilisée dans ma solution est celle de @Ozhan Duz, l'autre, similaire à la réponse @finnw où il a utilisé JACOB, et mérite d'être mentionnée est com4j - un échantillon utilisant WMI est disponible ici :

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));
}

Cela imprimera des informations sur l'ordinateur ainsi que le numéro de série de l'ordinateur. Veuillez noter que toutes les classes requises par cet exemple doivent être générées par maven-com4j-plugin. Exemple de configuration pour 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>

La configuration ci-dessus indiquera au plugin de générer des classes dans le répertoire target/generated-sources/com4j du dossier du projet.

Pour ceux qui souhaitent voir une solution prête à l'emploi , j'inclus des liens vers les trois classes que j'ai écrites pour obtenir la machine SN sur Windows, Linux et Mac OS:

44
Bartosz Firyn

Le projet OSHI fournit des utilitaires matériels indépendants de la plate-forme .

Dépendance Maven:

<dependency>
    <groupId>com.github.oshi</groupId>
    <artifactId>oshi-core</artifactId>
    <version>LATEST</version>
</dependency>

Par exemple, vous pouvez utiliser quelque chose comme le code suivant pour identifier une machine de manière unique:

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);
    }
}

Sortie pour ma machine:

Microsoft#57YRD12#Intel64 Family 6 Model 60 Stepping 3#8

Votre sortie sera différente car au moins le numéro de série du processeur sera différent.

25
BullyWiiPlaza

Que voulez-vous faire avec cet identifiant unique? Vous pouvez peut-être faire ce que vous voulez sans cet ID.

L'adresse MAC est peut-être une option mais ce n'est pas un ID unique de confiance car l'utilisateur peut modifier l'adresse MAC d'un ordinateur.

Pour obtenir la carte mère ou l'ID du processeur, vérifiez cela lien .

12
Pedro Ghilardi

Sur Windows uniquement, vous pouvez obtenir l'ID de la carte mère en utilisant WMI , via un pont COM tel que JACOB .

Exemple:

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();
        }
    }
}

Et si vous choisissez d'utiliser l'adresse MAC pour identifier la machine, vous pouvez utiliser WMI pour déterminer si une interface est connectée via USB (si vous souhaitez exclure les adaptateurs USB.)

Il est également possible d'obtenir un ID de disque dur via WMI, mais ce n'est pas fiable.

9
finnw

Soyez prudent lorsque vous utilisez l'adresse MAC comme identifiant. J'ai connu plusieurs pièges:

  1. Sous OS X, les ports Ethernet qui ne sont pas actifs/ne s'affichent pas dans l'énumération NetworkInterface.getNetworkInterfaces () .
  2. Il est incroyablement facile de changer une adresse MAC sur des cartes si vous disposez des privilèges de système d'exploitation appropriés.
  3. Java a l'habitude de ne pas identifier correctement les interfaces "virtuelles". Même en utilisant NetworkInterface.isVirtual () ne vous dira pas toujours la vérité.

Même avec les problèmes ci-dessus, je pense toujours que c'est la meilleure approche pure Java pour verrouiller le matériel d'une licence.

7
Jason Nichols

Ne connaissant pas toutes vos exigences. Par exemple, essayez-vous d'identifier de manière unique un ordinateur parmi tous les ordinateurs du monde, ou essayez-vous simplement d'identifier de manière unique un ordinateur parmi un ensemble d'utilisateurs de votre application. Pouvez-vous également créer des fichiers sur le système?

Si vous pouvez créer un fichier. Vous pouvez créer un fichier et utiliser l'heure de création du fichier comme identifiant unique. Si vous le créez dans l'espace utilisateur, il identifierait de manière unique un utilisateur de votre application sur une machine particulière. Si vous l'avez créé quelque part dans le monde, il pourrait identifier la machine de manière unique.

Encore une fois, comme la plupart des choses, à quelle vitesse est assez rapide .. ou dans ce cas, à quel point unique est assez unique.

6
sindri

Je pense que vous devriez regarder ceci lien ... vous pouvez créer une clé mixte en utilisant plusieurs identifiants tels que mac + os + nom d'hôte + id cp + série de la carte mère nombre .

3
Michel Gokan

L'utilisation de [~ # ~] mac [~ # ~] id est plus simple si la tâche consiste à enregistrer l'identifiant unique d'un système.

le changement d'identifiant mac est cependant possible, même le changement d'autres identifiants d'un système est également possible si le périphérique respectif est remplacé.

donc, à moins que ce qui est requis pour un identifiant unique ne soit pas connu, nous ne pourrons peut-être pas trouver une solution appropriée.

Cependant, le lien ci-dessous est utile pour extraire les adresses mac. http://www.stratos.me/2008/07/find-mac-address-using-Java/

1
Vamsy

Pour identifier une machine Windows de manière unique. Assurez-vous que lorsque vous utilisez wmic pour avoir une stratégie de méthodes alternatives. Étant donné que "wmic bios get serialnumber" peut ne pas fonctionner sur toutes les machines, vous devrez peut-être avoir des méthodes supplémentaires:

# 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

Ressources: la meilleure façon d'identifier de manière unique une machine Windows http://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine/

1
Basil Musa

Dans les programmes Java que j'ai écrits pour la sortie, j'ai utilisé le numéro de série de la carte mère (qui est ce que je crois que Windows utilise); cependant, cela ne fonctionne que sur Windows car ma fonction crée un script VB temporaire qui utilise le WMI pour récupérer la valeur.

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;
      }
0
Charles Eddy