我想获得以太网卡的MAC(产品密钥) 我尝试使用这种解决方案并在这里搜索,问题是当所有网络断开连接(以太网和wifi)时,它返回空MAC地址。 我宁愿得到以太网的地址,即使它已断开连接。
谢谢!
public static void main(String[] args)
{
InetAddress ip;
try {
ip = InetAddress.getLocalHost();
System.out.println("The mac Address of this machine is :" + ip.getHostAddress());
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
byte[] mac = network.getHardwareAddress();
System.out.print("The mac address is : ");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++){
sb.append(String.format("%02X%s", mac[i],(i< mac.length - 1)?"-":""));
}
System.out.println(sb.toString());
}
catch (UnknownHostException e) {
e.printStackTrace();
}
catch (SocketException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:4)
使用InetAddress
绑定您查看IP地址列表。如果没有,因为接口都已断开连接,那么你就无法遍历这些接口。
您应该尝试使用NetworkInterface
课程。
public class MacAddressTest
{
public static void main(String[] args) throws Exception
{
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements())
{
NetworkInterface nif = interfaces.nextElement();
byte[] lBytes = nif.getHardwareAddress();
StringBuffer lStringBuffer = new StringBuffer();
if (lBytes != null)
{
for (byte b : lBytes)
{
lStringBuffer.append(String.format("%1$02X ", new Byte(b)));
}
}
System.out.println(lStringBuffer);
}
}
}
答案 1 :(得分:1)
似乎Java标准库没有提供枚举所有网络接口的方法。
InetAddress
显然不适合,因为它代表IP地址。NetworkInterface
也不合适,因为它“表示由名称和分配给该接口的IP地址列表组成的网络接口” ,这意味着网络接口没有IP地址,则NetworkInterface
不适合表示它。确实可以肯定,尽管NetworkInterface.getNetworkInterfaces()
的javadoc说了“返回了这台机器上的所有接口” ,实际上,它仅返回了具有IP地址的网络接口。请注意,official tutorial会检索“所有”网络接口,也仅生成具有IP地址的网络接口的列表。
那你能做什么?
我认为您别无选择,只能寻找其他方法在运行时环境中查找此信息。
根据操作系统的不同,您可以通过解析文件系统中的文件来查找网络接口(如Linux中的this answer),或者通过解析系统命令(如ifconfig
)的输出来查找网络接口。 Windows中的* NIX或ipconfig
。
但是我认为这不会很强大,
因为您可能需要处理令人不快的问题,例如不同的行为,具体取决于操作系统版本或系统命令的可用性和版本。
另一种选择是使用一种语言开发一种可移植的跨平台工具,该工具能够本地获取网络接口列表,并以易于解析的一致格式生成它。然后,您可以将该工具捆绑在解决方案中。
Go是我想到的一个很好的候选人:它可以获取本地的网络接口列表,并且可以轻松地编译到所有必需的目标平台,并且二进制文件可以随时使用,而无需依赖于其他运行时环境。
这是一个简单的实现,用于打印网络接口列表,每行一个,名称,MAC和IP地址用制表符分隔:
package main
import (
"fmt"
"net"
"strings"
)
func macsAndIps() {
ifaces, err := net.Interfaces()
if err != nil {
fmt.Print(fmt.Errorf("could not get interfaces: %+v\n", err.Error()))
return
}
for _, iface := range ifaces {
addresses, err := iface.Addrs()
if err != nil {
fmt.Print(fmt.Errorf("could not get addresses for interface %v: %v\n", iface, err.Error()))
}
ips := []string{}
for _, address := range addresses {
// fmt.Printf("%#v\n", address)
switch address.(type) {
case *net.IPNet:
ips = append(ips, address.String())
}
}
name := iface.Name
mac := iface.HardwareAddr
fmt.Printf("%v\t%v\t%s\n", name, mac, strings.Join(ips, "\t"))
}
}
func main() {
macsAndIps()
}
答案 2 :(得分:1)
如果您要使用一些唯一的硬件标识符来验证许可证,那么我建议使用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
}
}
或者,您可以在this example file中看到很多硬件信息。