计算机特定的ID?

6
我正在尝试使用Java生成特定的计算机ID。我想到了一些方法,比如硬盘序列号、Windows序列密钥、CPU ID或MAC地址,但其他计算机可能具有相同的ID。例如,如果有人盗版了Windows 7,他们可能会拥有与某人相同的序列号。我想知道是否有一种方法可以生成一个特定于计算机且永不更改,并可在Java中检索的ID?
我做了一些研究并找到了一些有用的功能。我在考虑像这样的东西。但是,如果他们更改了硬件,它将更改计算机ID。有人知道我可以使用什么吗?
public String getComputerID(){
    InetAddress ip = InetAddress.getLocalHost();
    NetworkInterface network = NetworkInterface.getByInetAddress(ip);
    byte[] mac = network.getHardwareAddress();
    String sn = getSerialNumber("C");
    String cpuId = getMotherboardSN();
    return MD5(mac + sn + cpuId);
}


public String MD5(String md5) {
try {
        java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
        byte[] array = md.digest(md5.getBytes());
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < array.length; ++i) {
        sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
    }
        return sb.toString();
    } catch (java.security.NoSuchAlgorithmException e) {
    }
    return null;
}

public String getSerialNumber(String drive) {
String result = "";
    try {
    File file = File.createTempFile("realhowto",".vbs");
    file.deleteOnExit();
    FileWriter fw = new java.io.FileWriter(file);

  StringBufferring vbs = "Set objFSO = CreateObject(\"Scripting.FileSystemObject\")\n"
                +"Set colDrives = objFSO.Drives\n"
                +"Set objDrive = colDrives.item(\"" + drive + "\")\n"
                +"Wscript.Echo objDrive.SerialNumber";  // see note
    fw.write(vbs);
    FileWriter.close();
      Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
      BufferedReader input =
        new BufferedReader
        (new InputStreamReader(p.getInputStream()));
    String line;
    while ((line = input.readLine()) != null) {
        result += line;
    }
    input.close();
    }
    catch(Exception e){
        e.printStackTrace();
    }
    return result.trim();
}

public String getMotherboardSN() {
String result = "";
try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);

String vbs =
"Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
+ "Set colItems = objWMIService.ExecQuery _ \n"
+ " (\"Select * from Win32_BaseBoard\") \n"
+ "For Each objItem in colItems \n"
+ " Wscript.Echo objItem.SerialNumber \n"
+ " exit for ' do the first cpu only! \n"
+ "Next \n";

fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
result += line;
}
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return result.trim();
}

那么,你如何定义计算机的唯一性呢?我认为如果他们更改硬件,就会更改其ID。 - Chris Gerken
2
这将是版权所有者和数字版权管理技术创造者们长期以来的幻想实现。问题非常复杂,有无数的“陷阱”和妥协。祝好运! - le3th4x0rbot
3
但是你没有回答我的问题:计算机有什么使其独特的地方?如果我将计算机的所有部件(主板、驱动器等)移动到一个新箱子中,它还是同一台计算机吗? - Chris Gerken
2
我认为很难设计出一种算法,当运行时能够始终为同一台计算机提供相同的“计算机 ID”(即使在硬件更改的情况下也是如此),并且不会与其他计算机生成的 ID 冲突。适合的替代方案取决于您特定的用例,但最有可能涉及获取随机 ID(类似于 GUID 或由中央机构提供的已知唯一数字),并将此 ID 存储在稍后要识别的计算机上的某个地方。 - Arnout Engelen
1
正如@ChrisGerken所说,您需要定义什么构成“此”计算机,这是一个模糊的概念。在某些情况下,您可能认为它是封装 - “这个盒子”,但在其他情况下,您可能认为它是特定组件的组合 - “这个网络卡,这个主板,这些RAM插槽等”。许多人逐渐升级了多年的组件,当DRM或许可证方案突然决定我们拥有一个“新计算机”时,这确实令人恼火。 - Larry OBrien
显示剩余5条评论
3个回答

4

我认为你应该使用硬件配置文件中的某些内容。一台计算机可以被视为一组硬件部件,包括网络接口。一个典型的模式是将MAC地址和管理系统生成的ID组合在一起,该管理系统管理计算机网络。使用MAC地址在注册过程中唯一地标识机器。注册成功后,管理系统可以返回生成的唯一ID,存储在已注册的计算机上,并稍后使用。成功注册后,您可以更换网络接口卡,因为计算机不依赖于MAC地址来进行识别。您还可以考虑使用Linux dmidecode实用程序(对于Linux机器,由于您提供了基于Windows的解决方案,所以对于我们的Linux读者,我想提出一个Linux替代方案)(如果要唯一识别的机器安装有Linux和dmidecoe)。使用dmidecoe可以获得更多的硬件配置文件,并对其执行一些哈希函数,生成一个唯一的ID,以高概率唯一地标识您的机器。在此处阅读有关dmidecode的更多信息here。当然,在采用“从操作系统获取硬件信息”的方法时(这是dmidecode或您在获取MAC地址之后建议的方法),您需要跨平台代码来检查Java程序运行的操作系统,您可以使用以下方法:
System.getProperty("os.name");

具有提供唯一ID并将该ID存储在客户端计算机上的中央管理系统的概念是牢固的。然而,海报没有充分解释他的使用情况以确定该解决方案是否适用于他的情况。我不明白为什么在这种情况下您会使用客户机器的MAC地址或其他硬件属性。 - Arnout Engelen

1

对于磁盘/卷,可能是:

    /**
     * Execute system console command 'vol' and retrieve volume serial number
     *
     * @param driveLetter - drive letter in convetion 'X:'
     * @return - Volume Serial Number, typically: 'XXXX-XXXX'
     * @throws IOException
     * @throws InterruptedException
     */
    static final String getVolumeSerial(String driveLetter) throws IOException, InterruptedException {
        Process process = Runtime.getRuntime().exec("cmd /C vol " + driveLetter);
        InputStream inputStream = process.getInputStream();
        InputStream errorStream = process.getErrorStream();
        if (process.waitFor() != 0) {
            Scanner sce = new Scanner(errorStream);
            throw new RuntimeException(sce.findWithinHorizon(".*", 0));
        }
        Scanner scn = new Scanner(inputStream);
        // looking for: ': XXXX-XXXX' using regex
        String res = scn.findWithinHorizon(": \\w+-\\w+", 0);
        return res.substring(2).toUpperCase().trim();
    }

你好,抱歉如果这个问题看起来很幼稚,但是这个答案只适用于Windows系统,对吗? - Spencer D
是的,不幸的是只支持Windows操作系统。 - user3158918

1
在研究了每个人的意见,进行了许多谷歌搜索后,我得出了这个结论:
从技术上讲,如果您删除并更换了一个组件,它将成为一个全新的计算机,要生成真正的计算机专用ID,您必须从系统中的每个组件获取特定变量(例如序列号),将它们组合起来,就是“计算机特定ID”。然而,由于计算机易受到更改的影响,最接近的方法是选择最不容易更改的组件,并使用其中的特定变量作为计算机ID。这通常是主板或其他不太可能更改的组件。因此,最接近的可能会是主板的串行号码(或其他子组件)。这是我的个人观点。
为什么主板最不容易更改?
似乎主板是人们考虑更换的最后一部分,尤其是对于较新的计算机。除非绝对需要,否则他们通常不会更换它。另一个可行的选择是NIC。您可以自行决定使用哪个硬件,但最好使用您认为最不容易更改的硬件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接