2010-11-17 41 views
7

Tôi có địa chỉ IP và mặt nạ như 10.1.1.1/32. Tôi muốn kiểm tra nếu 10.1.1.1 nằm trong phạm vi đó. Có thư viện hay tiện ích nào có thể làm được điều này hay tôi cần phải tự mình viết một cái gì đó?Xác thực địa chỉ IP (với mặt nạ)

+2

có thể trùng lặp của [Có ai biết thành phần java để kiểm tra xem địa chỉ IP từ mạng cụ thể/mặt nạ mạng không?] (Http://stackoverflow.com/questions/577363/does-anyone-know-a- java-component-to-check-if-ip-address-là-from-specific-netwo) –

Trả lời

24

Trước tiên, bạn sẽ muốn chuyển đổi địa chỉ IP của bạn vào phẳng int s, mà sẽ được dễ dàng hơn để làm việc với:

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); 

Một khi bạn có địa chỉ IP của bạn là đồng bằng int s bạn có thể làm một số số học chút để thực hiện kiểm tra:

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

Giả sử tôi bắt đầu với 'String ip =" 10.1.1.1 "; int mask = 24' làm cách nào để nhận '0x0A010100'? –

+1

@ nn4l Cảm ơn, đã cập nhật câu trả lời của tôi để bao gồm chỉnh sửa của bạn. –

+1

Vì vậy, thực sự không có hỗ trợ cho điều này trong thư viện lớp cơ sở hoặc một số gói xử lý ủy quyền của bên thứ ba được đề xuất? – binki

1

Nhờ John Kugelman - tôi đã sử dụng đoạn mã của mình để tạo lớp này.

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; 
    } 

} 

tôi đã có thêm một mặt nạ để chuyển đổi int trong mã của mình:

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))); 

Được sản xuất:

ffffffc0 
c0c0c0c0 

Trên hệ thống của tôi:

$> 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) 
$> 

Bạn có thể loại bỏ các phương pháp chính và thử nghiệm từ c ở trên lass. Chúng được điều chỉnh từ mã kiểm tra đơn vị và được thêm vào đây để đơn giản.

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

Đây là phiên bản có mô tả mạng con theo một số cách phổ biến, bao gồm IPv6.

Dựa trên mã khác được đăng tại đây. Trên địa chỉ IPv4 địa chỉ, nó có thể hoạt động chậm hơn so với phương pháp thực hiện các phép toán nhị phân trên các số trống của 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)); 
     } 
    } 
} 
Các vấn đề liên quan