Saltar al contenido

¿Cómo verificar si una dirección IP es de una red / máscara de red en particular en Java?

Nuestros desarrolladores estrellas agotaron sus reservas de café, buscando noche y día por la resolución, hasta que Gabriela encontró el hallazgo en Beanstalk por lo tanto hoy la compartimos contigo.

Solución:

Opción 1:

Usar spring-security-webIpAddressMatcher. A diferencia de Apache Commons Net, admite tanto ipv4 como 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 de la parte anterior funciona perfectamente bien pero necesita spring-security-web ser incluido.

Si no está dispuesto a incluir el marco Spring en su proyecto, puede usar esta clase, que es una versión ligeramente modificada de la clase original de Spring, para que no tenga dependencias que no sean de JRE.

/*
 * 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.
 * 

* 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 JRE. */ 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);

AVISO: Tenga en cuenta que para usar esta opción, es su responsabilidad examinar cuidadosamente la licencia para asegurarse de que al usar este código, no está violando ninguno de los términos exigidos por la licencia mencionada anteriormente. (Por supuesto, publicar este código en Stackoverflow.com por mí no es una infracción).

Apache Commons Net tiene org.apache.commons.net.util.SubnetUtils que parece satisfacer sus necesidades. Parece que haces 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 señala Carson, que Apache Commons Net tiene un error que le impide dar la respuesta correcta en algunos casos. Carson sugiere usar la versión SVN para evitar este error.

También puedes probar

boolean inSubnet = (ip & netmask) == (subnet & netmask);

o mas corto

boolean inSubnet = (ip ^ subnet) & netmask == 0;

Te mostramos comentarios y puntuaciones

Eres capaz de sostener nuestra función escribiendo un comentario o puntuándolo te damos la bienvenida.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *