繁体   English   中英

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

[英]Java Get mac address of disconnected card

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

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

如果您希望使用某些唯一的硬件标识符来验证许可证,那么我建议您使用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 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;
}

似乎Java标准库没有提供枚举所有网络接口的方法。

  • InetAddress显然不合适,因为它代表IP地址。
  • NetworkInterface也不合适,因为它“代表一个由名称组成的网络接口,以及分配给该接口的IP地址列表” ,这意味着如果网络接口没有IP地址,则NetworkInterface是不适合代表它。 当然,尽管NetworkInterface.getNetworkInterfaces()的javadoc说“返回此机器上的所有接口” ,但事实上它只返回具有IP地址的网络接口。

请注意,检索“所有”网络接口的官方教程还会生成仅包含IP地址的网络接口的列表。

所以,你可以做什么?

我认为您别无选择,只能寻找其他方法在运行时环境中查找此信息。 根据操作系统的不同,您可以通过解析文件系统中的文件(如 Linux的答案 ),或通过解析系统命令的输出(如* NIX中的ifconfig或Windows中的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()
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM