2008-10-07 8 views
2

У меня есть следующие JSP-код, который защищает мой веб-страницу и отображает ее только знать IP-адресапроверка подсети IP в JSP

String ip_h = request.getRemoteAddr(); 
String host_h = request.getRemoteHost(); 
String iplist[] = new String[1]; 
iplist[0] = "127.0.0.1"; 
iplist[1] = "10.217.106.248"; 

int count = iplist.length; 
boolean flag = false; 
int zz = 0; 
//return; 
System.out.println(host_h); 
while ((flag==false) && (zz < count)) 
{ 
    if (ip_h.equals(iplist[zz]) || host_h.equals(iplist[zz])) 
    { 
     flag = true; 
    } 
    zz++; 
} 

Однако, я хотел бы, чтобы лучше проверить для диапазонов подсетей, то есть все пользователи, принадлежащей 10.217.0.0/16 разрешены.

Как это сделать?

+0

Нужно также поддерживать адрес ipv6? – MLefrancois 2011-04-18 15:45:13

ответ

2

IP-адреса (по крайней мере, IPv4-адреса) предназначены для представления в виде 32-разрядных целых чисел. Если сначала конвертировать IP-адрес в целое число, проверка диапазонов подсети становится относительно простым вопросом проверки (в вашем примере), соответствуют ли первые 16 бит первым 16 битам диапазона.

2

разве вы не использовали бы сервер приложений для блокировки диапазона ip? В апача вы можете создать псевдоним для каталога, поместите свой код в каталоге, то в директиве псевдонима позволяют только определенный IP или диапазоны:

Псевдоним/Mydir «/ USR/местные/MYDIR»

заказ отрицать, позволяют отрицать от всех разрешить от 10.217.106.248 разрешить от 127.0.0.1 позволяют из 10.217.106 # это диапазон

таким образом, вы не должны кодировать этот вид «магии номер "

Я уверен, что вы можете делать подобные вещи на других веб-серверах

0

Вы можете использовать следующий фрагмент кода, конечно, предполагается, что входные данные корректны, так что необходим украшая (на всякий случай)

public class IPUtil 
{ 

    private static int[] split(String ip) 
    { 
     int[] result = new int[4]; 
     StringTokenizer st = new StringTokenizer(ip, "."); 
     for (int i = 0; i < 4; i++) 
     { 
      result[i] = Integer.parseInt(st.nextToken()); 
     } 
     return result; 
    } 

    public static boolean matches(String visitorIpString, String ipString, String maskString) 
    { 
     int[] vip = split(visitorIpString); 
     int[] ip = split(ipString); 
     int[] mask = split(maskString); 

     for (int i = 0; i < 4; i++) 
     { 
      if ((vip[i] & mask[i]) != ip[i]) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 

    public static void main(String[] args) 
    { 

     String ip = "192.168.12.0"; 
     String mask = "255.255.255.0"; 
     String visitorIP = "192.168.12.55"; 

     System.out.println(matches(visitorIP, ip, mask)); 
    } 
} 
+0

Это поддерживает только ipv4 :( – MLefrancois 2011-04-18 15:43:08

2

Вы можете использовать этот класс IpRangeFilter. См. Комментарий к классу для объяснения.

import java.net.InetAddress; 
import java.net.UnknownHostException; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

import org.apache.commons.collections15.Predicate; 
import org.apache.commons.lang.builder.EqualsBuilder; 
import org.apache.commons.lang.builder.HashCodeBuilder; 

/** 
* I am a filter used to determine if a given IP Address is covered by the IP range specified in 
* the constructor. I accept IP ranges in the form of full single IP addresses, e.g. 10.1.0.23 
* or network/netmask pairs in CIDR format e.g. 10.1.0.0/16 
*/ 
public class IpRangeFilter implements Predicate<InetAddress> { 

    private final long network; 
    private final long netmask; 

    private final String ipRange; 

    private static final Pattern PATTERN = Pattern.compile("((?:\\d|\\.)+)(?:/(\\d{1,2}))?"); 

    public IpRangeFilter(String ipRange) throws UnknownHostException { 
     Matcher matcher = PATTERN.matcher(ipRange); 
     if (matcher.matches()) { 
      String networkPart = matcher.group(1); 
      String cidrPart = matcher.group(2); 

      long netmask = 0; 
      int cidr = cidrPart == null ? 32 : Integer.parseInt(cidrPart); 
      for (int pos = 0; pos < 32; ++pos) { 
       if (pos >= 32-cidr) { 
        netmask |= (1L << pos); 
       } 
      } 

      this.network = netmask & toMask(InetAddress.getByName(networkPart)); 
      this.netmask = netmask; 
      this.ipRange = ipRange; 

     } else { 
      throw new IllegalArgumentException("Not a valid IP range: " + ipRange); 
     } 
    } 

    public String getIpRange() { 
     return ipRange; 
    } 

    public boolean evaluate(InetAddress address) { 
     return isInRange(address); 
    } 

    public boolean isInRange(InetAddress address) { 
     return network == (toMask(address) & netmask); 
    } 

    /** 
    * Convert the bytes in the InetAddress into a bit mask stored as a long. 
    * We could use int's here, but java represents those in as signed numbers, which can be a pain 
    * when debugging. 
    * @see http://www.captain.at/howto-java-convert-binary-data.php 
    */ 
    static long toMask(InetAddress address) { 
     byte[] data = address.getAddress(); 
     long accum = 0; 
     int idx = 3; 
     for (int shiftBy = 0; shiftBy < 32; shiftBy += 8) { 
      accum |= ((long)(data[idx] & 0xff)) << shiftBy; 
      idx--; 
     } 
     return accum; 
    } 
}