¿Alguien sabe un componente de Java para comprobar si la dirección IP es de particular, la red / máscara de red? [cerrado]
-
05-09-2019 - |
Pregunta
necesito para determinar si la dirección IP dada es desde alguna red especial que debe autenticar automáticamente.
Solución
Apache Commons Net tiene org.apache.commons.net.util.SubnetUtils
que aparece para satisfacer sus necesidades. Parece que se hace algo como esto:
SubnetInfo subnet = (new SubnetUtils("10.10.10.0", "255.255.255.128")).getInfo();
boolean test = subnet.isInRange("10.10.10.10");
Tenga en cuenta, como Carson señala, que Apache Commons Net tiene una error que le impide dar la respuesta correcta en algunos casos. Carson sugiere el uso de la versión SVN para evitar este error.
Otros consejos
Opción 1:
spring-security-web
's IpAddressMatcher . A diferencia de Apache Commons Net, es compatible con IPv4 e IPv6.
import org.springframework.security.web.util.matcher.IpAddressMatcher;
...
private void checkIpMatch() {
matches("192.168.2.1", "192.168.2.1"); // true
matches("192.168.2.1", "192.168.2.0/32"); // false
matches("192.168.2.5", "192.168.2.0/24"); // true
matches("92.168.2.1", "fe80:0:0:0:0:0:c0a8:1/120"); // false
matches("fe80:0:0:0:0:0:c0a8:11", "fe80:0:0:0:0:0:c0a8:1/120"); // true
matches("fe80:0:0:0:0:0:c0a8:11", "fe80:0:0:0:0:0:c0a8:1/128"); // false
matches("fe80:0:0:0:0:0:c0a8:11", "192.168.2.0/32"); // false
}
private boolean matches(String ip, String subnet) {
IpAddressMatcher ipAddressMatcher = new IpAddressMatcher(subnet);
return ipAddressMatcher.matches(ip);
}
Opción 2 (una solución ligera!):
El código en la parte anterior funciona perfectamente bien pero necesita spring-security-web
a ser incluido.
Si usted no está dispuesto a incluir marco de primavera en su proyecto, puede utilizar esta clase que es una versión ligeramente modificada de la clase original de la primavera, por lo que no tiene ninguna dependencias -JDK.
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* Matches a request based on IP Address or subnet mask matching against the remote
* address.
* <p>
* Both IPv6 and IPv4 addresses are supported, but a matcher which is configured with an
* IPv4 address will never match a request which returns an IPv6 address, and vice-versa.
*
* @author Luke Taylor
* @since 3.0.2
*
* Slightly modified by omidzk to have zero dependency to any frameworks other than the JDK.
*/
public final class IpAddressMatcher {
private final int nMaskBits;
private final InetAddress requiredAddress;
/**
* Takes a specific IP address or a range specified using the IP/Netmask (e.g.
* 192.168.1.0/24 or 202.24.0.0/14).
*
* @param ipAddress the address or range of addresses from which the request must
* come.
*/
public IpAddressMatcher(String ipAddress) {
if (ipAddress.indexOf('/') > 0) {
String[] addressAndMask = ipAddress.split("/");
ipAddress = addressAndMask[0];
nMaskBits = Integer.parseInt(addressAndMask[1]);
}
else {
nMaskBits = -1;
}
requiredAddress = parseAddress(ipAddress);
assert (requiredAddress.getAddress().length * 8 >= nMaskBits) :
String.format("IP address %s is too short for bitmask of length %d",
ipAddress, nMaskBits);
}
public boolean matches(String address) {
InetAddress remoteAddress = parseAddress(address);
if (!requiredAddress.getClass().equals(remoteAddress.getClass())) {
return false;
}
if (nMaskBits < 0) {
return remoteAddress.equals(requiredAddress);
}
byte[] remAddr = remoteAddress.getAddress();
byte[] reqAddr = requiredAddress.getAddress();
int nMaskFullBytes = nMaskBits / 8;
byte finalByte = (byte) (0xFF00 >> (nMaskBits & 0x07));
// System.out.println("Mask is " + new sun.misc.HexDumpEncoder().encode(mask));
for (int i = 0; i < nMaskFullBytes; i++) {
if (remAddr[i] != reqAddr[i]) {
return false;
}
}
if (finalByte != 0) {
return (remAddr[nMaskFullBytes] & finalByte) == (reqAddr[nMaskFullBytes] & finalByte);
}
return true;
}
private InetAddress parseAddress(String address) {
try {
return InetAddress.getByName(address);
}
catch (UnknownHostException e) {
throw new IllegalArgumentException("Failed to parse address" + address, e);
}
}
}
Dif:
+ *
+ * Slightly modified by omidzk to have zero dependency to any frameworks other than the JDK.
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.security.web.util.matcher.RequestMatcher;
-import org.springframework.util.StringUtils;
-import org.springframework.util.Assert;
-public final class IpAddressMatcher implements RequestMatcher {
+public final class IpAddressMatcher {
- String[] addressAndMask = StringUtils.split(ipAddress, "/");
+ String[] addressAndMask = ipAddress.split("/");
- Assert.isTrue(requiredAddress.getAddress().length * 8 >= nMaskBits,
+ assert (requiredAddress.getAddress().length * 8 >= nMaskBits) :
- ipAddress, nMaskBits));
+ ipAddress, nMaskBits);
-
- public boolean matches(HttpServletRequest request) {
- return matches(request.getRemoteAddr());
- }
AVISO: : Tenga en cuenta que para utilizar esta opción, es su responsabilidad de examinar cuidadosamente la licencia para asegurarse de que mediante el uso de este código, usted no está en violación de cualquiera de los términos establecidos por la referida licencia. (Por supuesto, la publicación de este código para Stackoverflow.com por mí, no es una violación.)
También puede intentar
boolean inSubnet = (ip & netmask) == (subnet & netmask);
o más corto
boolean inSubnet = (ip ^ subnet) & netmask == 0;
La biblioteca de código abierto de Java DirecciónIP va a hacer esto de una forma polimórfica para IPv4 e IPv6 y se ocupa de las subredes. Exención de responsabilidad: yo soy el director del proyecto de la biblioteca
.código de ejemplo:
contains("10.10.20.0/30", "10.10.20.3");
contains("10.10.20.0/30", "10.10.20.5");
contains("1::/64", "1::1");
contains("1::/64", "2::1");
contains("1::3-4:5-6", "1::4:5");
contains("1-2::/64", "2::");
contains("bla", "foo");
static void contains(String network, String address) {
IPAddressString one = new IPAddressString(network);
IPAddressString two = new IPAddressString(address);
System.out.println(one + " contains " + two + " " + one.contains(two));
}
Salida:
10.10.20.0/30 contains 10.10.20.3 true
10.10.20.0/30 contains 10.10.20.5 false
1::/64 contains 1::1 true
1::/64 contains 2::1 false
1::3-4:5-6 contains 1::4:5 true
1-2::/64 contains 2:: true
bla contains foo false
Para comprobar un CI en una subred, he utilizado el método en la clase EstaEnRango SubnetUtils. Pero este método tiene un error que si su subred era X, todas las direcciones IP que menor que X, EstaEnRango return true. Por ejemplo si su subred era 10.10.30.0/24 y desea comprobar 10.10.20.5, este método devuelve true. Para hacer frente a este error que se utiliza por debajo de código.
public static void main(String[] args){
String list = "10.10.20.0/24";
String IP1 = "10.10.20.5";
String IP2 = "10.10.30.5";
SubnetUtils subnet = new SubnetUtils(list);
SubnetUtils.SubnetInfo subnetInfo = subnet.getInfo();
if(MyisInRange(subnetInfo , IP1) == true)
System.out.println("True");
else
System.out.println("False");
if(MyisInRange(subnetInfo , IP2) == true)
System.out.println("True");
else
System.out.println("False");
}
private boolean MyisInRange(SubnetUtils.SubnetInfo info, String Addr )
{
int address = info.asInteger( Addr );
int low = info.asInteger( info.getLowAddress() );
int high = info.asInteger( info.getHighAddress() );
return low <= address && address <= high;
}
aquí es una versión que funciona con IPv4 e IPv6 con un prefijo y una con máscara de red.
/**
* Check if IP is within an Subnet defined by Network Address and Network Mask
* @param ip
* @param net
* @param mask
* @return
*/
public static final boolean isIpInSubnet(final String ip, final String net, final int prefix) {
try {
final byte[] ipBin = java.net.InetAddress.getByName(ip ).getAddress();
final byte[] netBin = java.net.InetAddress.getByName(net ).getAddress();
if(ipBin.length != netBin.length ) return false;
int p = prefix;
int i = 0;
while(p>=8) { if(ipBin[i] != netBin[i] ) return false; ++i; p-=8; }
final int m = (65280 >> p) & 255;
if((ipBin[i] & m) != (netBin[i]&m) ) return false;
return true;
} catch(final Throwable t) {
return false;
}
}
/**
* Check if IP is within an Subnet defined by Network Address and Network Mask
* @param ip
* @param net
* @param mask
* @return
*/
public static final boolean isIpInSubnet(final String ip, final String net, final String mask) {
try {
final byte[] ipBin = java.net.InetAddress.getByName(ip ).getAddress();
final byte[] netBin = java.net.InetAddress.getByName(net ).getAddress();
final byte[] maskBin = java.net.InetAddress.getByName(mask).getAddress();
if(ipBin.length != netBin.length ) return false;
if(netBin.length != maskBin.length) return false;
for(int i = 0; i < ipBin.length; ++i) if((ipBin[i] & maskBin[i]) != (netBin[i] & maskBin[i])) return false;
return true;
} catch(final Throwable t) {
return false;
}
}
Sé que esto es muy vieja pregunta, pero me encontré con este cuando yo estaba buscando para resolver el mismo problema.
No es Commons-ip-matemáticas biblioteca que creo que hace un muy buen trabajo. Tenga en cuenta que en mayo de 2019, no ha habido ninguna cambios a la biblioteca (podría ser que su biblioteca ya muy maduro). Su disponible en experto-centro
Es compatible con el trabajo con ambas direcciones IPv4 e IPv6. Su breve documentación tiene ejemplos de cómo se puede comprobar si una dirección está en un rango específico de IPv4 y IPv6
Ejemplo para IPv4 verificación de rango:
String input1 = "192.168.1.0";
Ipv4 ipv41 = Ipv4.parse(input1);
// Using CIDR notation to specify the networkID and netmask
Ipv4Range range = Ipv4Range.parse("192.168.0.0/24");
boolean result = range.contains(ipv41);
System.out.println(result); //false
String input2 = "192.168.0.251";
Ipv4 ipv42 = Ipv4.parse(input2);
// Specifying the range with a start and end.
Ipv4 start = Ipv4.of("192.168.0.0");
Ipv4 end = Ipv4.of("192.168.0.255");
range = Ipv4Range.from(start).to(end);
result = range.contains(ipv42); //true
System.out.println(result);