如果您希望使用一些唯一的硬件标识符来验证许可证,那么我建议您使用OSHI(操作系统和硬件信息)来获取您需要的硬件信息。
一般主体会将硬件标识符编码到客户端许可证字符串中,然后当客户端运行时,它将从许可证字符串中解码该 ID,并确保存在硬件以验证许可证。不要依赖索引,因为通常无法保证硬件顺序,只需遍历有问题的硬件列表并查看键绑定的硬件是否存在。
注意:在本地完成许可证验证时,总是可以破解;关键是让破解变得烦人。如果您的许可证本身只是普通的 MAC 地址,那么人们很容易查找他们的 MAC 并给自己一个有效的许可证。即使您将 MAC 编码/加密到许可证中,他们也可以查看反编译的代码并找到解码(以及因此编码)的工作原理,以便他们可以对自己的有效许可证进行编码。您需要尽可能多地加密和混淆,以使人们难以生成自己的许可证,但最终它只会使破解变得更加烦人,但并非不可能。
除了 MAC 地址之外,另一个选项是绑定到磁盘。磁盘序列号不像MAC地址那样容易更改。有了这个,您可以将许可证绑定到 USB 密钥,这很有趣。唯一需要担心的是人们更换磁盘,但如果软件许可证绑定到存储它的磁盘,那么这几乎不是问题。
pom.xml
...
<dependencies>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>3.13.2</version>
</dependency>
</dependencies>
...
ClientLicense.java
import oshi.SystemInfo;
import oshi.hardware.HWDiskStore;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.hardware.NetworkIF;
/**
* This class would be loaded with the client license and validate that the license is for the machine running this code.
*/
public class ClientLicense {
final String clientLicenseString;
public ClientLicense(String clientLicenseString) {
this.clientLicenseString = clientLicenseString;
}
public final boolean validateByDisk() {
int expectedModelSerialHash = decodeExpectedModelSerialHash(clientLicenseString);
for (HWDiskStore disk : new SystemInfo().getHardware().getDiskStores()) {
if (expectedModelSerialHash == Objects.hash(disk.getModel(), disk.getSerial())) {
return true;
}
}
return false;
}
public final boolean validateByMAC() {
String expectedMac = decodeExpectedMac(clientLicenseString);
for (NetworkIF netIF : new SystemInfo().getHardware().getNetworkIFs()) {
if (expectedMac.equals(netIF.getMacaddr())) {
return true;
}
}
return false;
}
private int decodeExpectedModelSerialHash(String clientLicenseString) {
// obfuscate license decoding, inverse of license encoding/encrypting
return 0; // return the expected hash of model and serial
}
private String decodeExpectedMac(String clientLicenseString) {
// obfuscate license decoding, inverse of license encoding/encrypting
return ""; // return the expected MAC address
}
}
或者,您可以在此示例文件中看到很多硬件信息。
此外,请参阅oshi-demo
(如 Daniel Widdis 所述)的示例类;该ComputerID.java
示例包含以下方法:
/**
* Generates a Computer Identifier, which may be part of a strategy to
* construct a licence key. (The identifier may not be unique as in one case
* hashcode could be same for multiple values, and the result may differ
* based on whether the program is running with sudo/root permission.) The
* identifier string is based upon the processor serial number, vendor,
* processor identifier, and total processor count.
*
* @return A string containing four hyphen-delimited fields representing the
* processor; the first 3 are 32-bit hexadecimal values and the last
* one is an integer value.
*/
public static String getComputerIdentifier() {
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 String.format("%08x", vendor.hashCode()) + delimiter
+ String.format("%08x", processorSerialNumber.hashCode()) + delimiter
+ String.format("%08x", processorIdentifier.hashCode()) + delimiter + processors;
}