2010-11-17 109 views
7

我有IP地址和掩码,例如10.1.1.1/32。我想检查10.1.1.1是否在该范围内。是否有一个库或实用程序会这样做,或者我需要自己写一些东西?验证IP地址(带掩码)

+2

的可能重复[有谁知道一个Java组件来检查,如果IP地址是从特定的网络/网络掩码?(http://stackoverflow.com/questions/577363/does-anyone-know-a- java-component-to-check-if-ip-address-is-from-particular-netwo) – 2010-11-18 00:37:15

回答

24

首先你要你的IP地址转换为平板int s,这将是比较容易的工作:

String  s = "10.1.1.99"; 
Inet4Address a = (Inet4Address) InetAddress.getByName(s); 
byte[]  b = a.getAddress(); 
int   i = ((b[0] & 0xFF) << 24) | 
       ((b[1] & 0xFF) << 16) | 
       ((b[2] & 0xFF) << 8) | 
       ((b[3] & 0xFF) << 0); 

一旦你有你的IP地址为纯int是你可以做一些位算术执行检查:

int subnet = 0x0A010100; // 10.1.1.0/24 
int bits = 24; 
int ip  = 0x0A010199; // 10.1.1.99 

// Create bitmask to clear out irrelevant bits. For 10.1.1.0/24 this is 
// 0xFFFFFF00 -- the first 24 bits are 1's, the last 8 are 0's. 
// 
//  -1  == 0xFFFFFFFF 
//  32 - bits == 8 
//  -1 << 8 == 0xFFFFFF00 
mask = -1 << (32 - bits) 

if ((subnet & mask) == (ip & mask)) { 
    // IP address is in the subnet. 
} 
+1

假设我以'String ip =“10.1.1.1”开始; int mask = 24'我如何获得'0x0A010100'? – 2010-11-18 15:41:41

+1

@ nn4l谢谢,更新了我的答案,包括您的更正。 – 2012-02-27 21:08:32

+1

因此,在基类库或某些推荐的第三方网络掩码处理软件包中确实没有对此提供支持? – binki 2015-04-02 04:22:31

1

感谢约翰库格尔曼 - 我用他的代码片段来创建这个类。

package bs; 

import java.net.Inet4Address; 
import java.net.InetAddress; 
import java.net.UnknownHostException; 

/** 
* Represents an IP range based on an address/mask. 
* @author Scott Plante, using code snippets by John Kugelman. 
*/ 
public class IPMask 
{ 
    public static void main(String args[]) 
     throws UnknownHostException 
    { 
    IPMask ipmask; 

    ipmask = IPMask.getIPMask("192.168.20.32/24"); 
    System.out.println("Checking "+ipmask+"..."); 

    test(ipmask, "192.168.20.31 ", true); 
    test(ipmask, "192.168.20.32 ", true); 
    test(ipmask, "192.168.20.33 ", true); 
    test(ipmask, "192.168.20.34 ", true); 
    test(ipmask, "192.168.20.35 ", true); 
    test(ipmask, "192.168.20.36 ", true); 
    test(ipmask, "192.168.20.254", true); 
    test(ipmask, "192.168.20.157", true); 
    test(ipmask, "192.168.21.1 ", false); 
    test(ipmask, "192.168.19.255", false); 
    test(ipmask, "192.168.24.1 ", false); 

    ipmask = IPMask.getIPMask("192.168.20.32/31"); 
    System.out.println("Checking "+ipmask+"..."); 

    test(ipmask, "192.168.20.31 ", false); 
    test(ipmask, "192.168.20.32 ", true); 
    test(ipmask, "192.168.20.33 ", true); 
    test(ipmask, "192.168.20.34 ", false); 
    test(ipmask, "192.168.20.35 ", false); 
    test(ipmask, "192.168.20.36 ", false); 
    test(ipmask, "192.168.20.254", false); 
    test(ipmask, "192.168.20.157", false); 
    test(ipmask, "192.168.21.1 ", false); 
    test(ipmask, "192.168.19.255", false); 
    test(ipmask, "192.168.24.1 ", false); 

    ipmask = IPMask.getIPMask("192.168.20.32/23"); 
    System.out.println("Checking "+ipmask+"..."); 

    test(ipmask, "192.168.20.31 ", true); 
    test(ipmask, "192.168.20.32 ", true); 
    test(ipmask, "192.168.20.33 ", true); 
    test(ipmask, "192.168.20.254", true); 
    test(ipmask, "192.168.21.254", true); 
    test(ipmask, "192.168.19.255", false); 
    test(ipmask, "192.168.24.1 ", false); 

    } 

    public static void test(IPMask ipmask, String addr, boolean expect) 
     throws UnknownHostException 
    { 
    boolean got = ipmask.matches(addr); 
    System.out.println(addr + "\t(" + expect + ") ?\t"+got 
     + "\t" + (got==expect?"":"!!!!!!!!")); 
    } 

    private Inet4Address i4addr; 
    private byte maskCtr; 

    private int addrInt; 
    private int maskInt; 

    public IPMask(Inet4Address i4addr, byte mask) 
    { 
    this.i4addr = i4addr; 
    this.maskCtr = mask; 

    this.addrInt = addrToInt(i4addr); 
    this.maskInt = ~((1 << (32 - maskCtr)) - 1); 
    } 

    /** IPMask factory method. 
    * 
    * @param addrSlashMask IP/Mask String in format "nnn.nnn.nnn.nnn/mask". If 
    * the "/mask" is omitted, "/32" (just the single address) is assumed. 
    * @return a new IPMask 
    * @throws UnknownHostException if address part cannot be parsed by 
    * InetAddress 
    */ 
    public static IPMask getIPMask(String addrSlashMask) 
     throws UnknownHostException 
    { 
    int pos = addrSlashMask.indexOf('/'); 
    String addr; 
    byte maskCtr; 
    if (pos==-1) 
    { 
     addr = addrSlashMask; 
     maskCtr = 32; 
    } 
    else 
    { 
     addr = addrSlashMask.substring(0, pos); 
     maskCtr = Byte.parseByte(addrSlashMask.substring(pos + 1)); 
    } 
    return new IPMask((Inet4Address) InetAddress.getByName(addr), maskCtr); 
    } 

/** Test given IPv4 address against this IPMask object. 
    * 
    * @param testAddr address to check. 
    * @return true if address is in the IP Mask range, false if not. 
    */ 
    public boolean matches(Inet4Address testAddr) 
    { 
    int testAddrInt = addrToInt(testAddr); 
    return ((addrInt & maskInt) == (testAddrInt & maskInt)); 
    } 

/** Convenience method that converts String host to IPv4 address. 
    * 
    * @param addr IP address to match in nnn.nnn.nnn.nnn format or hostname. 
    * @return true if address is in the IP Mask range, false if not. 
    * @throws UnknownHostException if the string cannot be decoded. 
    */ 
    public boolean matches(String addr) 
     throws UnknownHostException 
    { 
    return matches((Inet4Address)InetAddress.getByName(addr)); 
    } 

/** Converts IPv4 address to integer representation. 
    */ 
    private static int addrToInt(Inet4Address i4addr) 
    { 
    byte[] ba = i4addr.getAddress(); 
    return (ba[0]  << 24) 
     | ((ba[1]&0xFF) << 16) 
     | ((ba[2]&0xFF) << 8) 
     | (ba[3]&0xFF); 
    } 

    @Override 
    public String toString() 
    { 
    return "IPMask(" + i4addr.getHostAddress() + "/" + maskCtr + ")"; 
    } 

    @Override 
    public boolean equals(Object obj) 
    { 
    if (obj == null) 
     return false; 
    if (getClass() != obj.getClass()) 
     return false; 
    final IPMask that = (IPMask) obj;  
    return (this.addrInt == that.addrInt && this.maskInt == that.maskInt); 
    } 

    @Override 
    public int hashCode() 
    { 
    return this.maskInt + this.addrInt; 
    } 

} 

我确实有一个面具添加到自己的代码中的int转换:

Inet4Address a = (Inet4Address) InetAddress.getByName("192.192.192.192"); 
byte[]  b = a.getAddress(); 
int   i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0); 
System.out.println(Integer.toHexString(i)); 
System.out.println(Integer.toHexString(addrToInt(a))); 

制作:

ffffffc0 
c0c0c0c0 

在我的系统:

$> uname -a 
Linux guin 2.6.37.6-0.5-desktop #1 SMP PREEMPT 2011-04-25 21:48:33 +0200 x86_64 x86_64 x86_64 GNU/Linux 
$> java -version 
java version "1.6.0_25" 
Java(TM) SE Runtime Environment (build 1.6.0_25-b06) 
Java HotSpot(TM) 64-Bit Server VM (build 20.0-b11, mixed mode) 
$> 

你可以从上面的c中删除主要和测试方法姑娘。它们根据单元测试代码进行了修改,并且为了简化而添加到此处

3
public static boolean netMatch(String addr, String addr1){ //addr is subnet address and addr1 is ip address. Function will return true, if addr1 is within addr(subnet) 

     String[] parts = addr.split("/"); 
     String ip = parts[0]; 
     int prefix; 

     if (parts.length < 2) { 
      prefix = 0; 
     } else { 
      prefix = Integer.parseInt(parts[1]); 
     } 

     Inet4Address a =null; 
     Inet4Address a1 =null; 
     try { 
      a = (Inet4Address) InetAddress.getByName(ip); 
      a1 = (Inet4Address) InetAddress.getByName(addr1); 
     } catch (UnknownHostException e){} 

     byte[] b = a.getAddress(); 
     int ipInt = ((b[0] & 0xFF) << 24) | 
         ((b[1] & 0xFF) << 16) | 
         ((b[2] & 0xFF) << 8) | 
         ((b[3] & 0xFF) << 0); 

     byte[] b1 = a1.getAddress(); 
     int ipInt1 = ((b1[0] & 0xFF) << 24) | 
         ((b1[1] & 0xFF) << 16) | 
         ((b1[2] & 0xFF) << 8) | 
         ((b1[3] & 0xFF) << 0); 

     int mask = ~((1 << (32 - prefix)) - 1); 

     if ((ipInt & mask) == (ipInt1 & mask)) { 
      return true; 
     } 
     else { 
      return false; 
     } 
} 
3

这里是一个版本,发生在几种常见方式子网的描述,包括IPv6的

根据此处发布的其他代码。 对IPv4解决这个问题的方法可能比在int上执行二进制操作的方法要慢。

package de.c3oe.tryanderror; 
import java.math.BigInteger; 
import java.net.InetAddress; 
import java.net.UnknownHostException; 

/** 
* @author c3oe.de, based on snippets from Scott Plante, John Kugelmann 
*/ 
public class Subnet 
{ 
    final private int bytesSubnetCount; 
    final private BigInteger bigMask; 
    final private BigInteger bigSubnetMasked; 

    /** For use via format "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57" */ 
    public Subnet(final InetAddress subnetAddress, final int bits) 
    { 
     this.bytesSubnetCount = subnetAddress.getAddress().length; // 4 or 16 
     this.bigMask = BigInteger.valueOf(-1).shiftLeft(this.bytesSubnetCount*8 - bits); // mask = -1 << 32 - bits 
     this.bigSubnetMasked = new BigInteger(subnetAddress.getAddress()).and(this.bigMask); 
    } 

    /** For use via format "192.168.0.0/255.255.255.0" or single address */ 
    public Subnet(final InetAddress subnetAddress, final InetAddress mask) 
    { 
     this.bytesSubnetCount = subnetAddress.getAddress().length; 
     this.bigMask = null == mask ? BigInteger.valueOf(-1) : new BigInteger(mask.getAddress()); // no mask given case is handled here. 
     this.bigSubnetMasked = new BigInteger(subnetAddress.getAddress()).and(this.bigMask); 
    } 

    /** 
    * Subnet factory method. 
    * @param subnetMask format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0" 
    *  or single address or "2001:db8:85a3:880:0:0:0:0/57" 
    * @return a new instance 
    * @throws UnknownHostException thrown if unsupported subnet mask. 
    */ 
    public static Subnet createInstance(final String subnetMask) 
      throws UnknownHostException 
    { 
     final String[] stringArr = subnetMask.split("/"); 
     if (2 > stringArr.length) 
      return new Subnet(InetAddress.getByName(stringArr[ 0 ]), (InetAddress)null); 
     else if (stringArr[ 1 ].contains(".") || stringArr[ 1 ].contains(":")) 
      return new Subnet(InetAddress.getByName(stringArr[ 0 ]), InetAddress.getByName(stringArr[ 1 ])); 
     else 
      return new Subnet(InetAddress.getByName(stringArr[ 0 ]), Integer.parseInt(stringArr[ 1 ])); 
    } 

    public boolean isInNet(final InetAddress address) 
    { 
     final byte[] bytesAddress = address.getAddress(); 
     if (this.bytesSubnetCount != bytesAddress.length) 
      return false; 
     final BigInteger bigAddress = new BigInteger(bytesAddress); 
     return bigAddress.and(this.bigMask).equals(this.bigSubnetMasked); 
    } 

    @Override 
    final public boolean equals(Object obj) 
    { 
     if (! (obj instanceof Subnet)) 
      return false; 
     final Subnet other = (Subnet)obj; 
     return this.bigSubnetMasked.equals(other.bigSubnetMasked) && 
       this.bigMask.equals(other.bigMask) && 
       this.bytesSubnetCount == other.bytesSubnetCount; 
    } 

    @Override 
    final public int hashCode() 
    { 
     return this.bytesSubnetCount; 
    } 

    @Override 
    public String toString() 
    { 
     final StringBuilder buf = new StringBuilder(); 
     bigInteger2IpString(buf, this.bigSubnetMasked, this.bytesSubnetCount); 
     buf.append('/'); 
     bigInteger2IpString(buf, this.bigMask, this.bytesSubnetCount); 
     return buf.toString(); 
    } 

    static private void bigInteger2IpString(final StringBuilder buf, final BigInteger bigInteger, final int displayBytes) 
    { 
     final boolean isIPv4 = 4 == displayBytes; 
     byte[] bytes = bigInteger.toByteArray(); 
     int diffLen = displayBytes - bytes.length; 
     final byte fillByte = 0 > (int)bytes[ 0 ] ? (byte)0xFF : (byte)0x00; 

     int integer; 
     for (int i = 0; i < displayBytes; i++) 
     { 
      if (0 < i && ! isIPv4 && i % 2 == 0) 
       buf.append(':'); 
      else if (0 < i && isIPv4) 
       buf.append('.'); 
      integer = 0xFF & (i < diffLen ? fillByte : bytes[ i - diffLen ]); 
      if (! isIPv4 && 0x10 > integer) 
       buf.append('0'); 
      buf.append(isIPv4 ? integer : Integer.toHexString(integer)); 
     } 
    } 
}