Java获取断开连接卡的mac地址

时间:2012-08-27 16:18:42

标签: java networking

我想获得以太网卡的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();
        }
    }
}

3 个答案:

答案 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中看到很多硬件信息。