Kennt jemand eine Java-Komponente zu überprüfen, ob die IP-Adresse von bestimmtem Netzwerk / netmask ist? [geschlossen]
-
05-09-2019 - |
Frage
ich brauche, um zu bestimmen, ob bestimmte IP-Adresse von einem speziellen Netzwerk ist i automatisch authentifizieren muss.
Lösung
Apache Commons Net org.apache.commons.net.util.SubnetUtils
hat, die Ihren Bedürfnissen gerecht zu werden scheint. Es sieht aus wie Sie etwas tun:
SubnetInfo subnet = (new SubnetUtils("10.10.10.0", "255.255.255.128")).getInfo();
boolean test = subnet.isInRange("10.10.10.10");
Beachten Sie, wie carson weist darauf hin, dass Apache Commons Net hat
Andere Tipps
Option 1:
Verwenden Sie spring-security-web
's IpAddressMatcher . Im Gegensatz zu Apache Commons Net unterstützt es sowohl IPv4- als auch 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);
}
Option 2 (eine leichte Lösung!):
Der Code in vorherigem Teil funktioniert völlig in Ordnung , aber es braucht spring-security-web
aufgenommen werden.
Wenn Sie nicht bereit sind, zu Spring-Framework in Ihrem Projekt enthält, können Sie diese Klasse verwenden, das ist eine leicht modifizierte Version des Original-Klasse aus Spring, so dass es keine nicht hat -jdk Abhängigkeiten.
/*
* 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);
}
}
}
Diff:
+ *
+ * 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());
- }
ACHTUNG: : Beachten Sie, dass diese Option für die Nutzung, ist es in Ihrer Verantwortung, sorgfältig die Lizenz um sicherzustellen, dass durch diesen Code verwenden, sind Sie nicht in der Verletzung von Bedingungen durch die zuvor genannte Lizenz vorgeschrieben ist. (Natürlich Veröffentlichung diesen Code Stackoverflow.com von mir nicht eine Verletzung).
Sie können auch versuchen
boolean inSubnet = (ip & netmask) == (subnet & netmask);
oder kürzer
boolean inSubnet = (ip ^ subnet) & netmask == 0;
Die Open-Source-Java-Bibliothek IPAddress diese in einer polymorphen Weise für IPv4 tun und IPv6 und Griffe Subnetze. Disclaimer: Ich bin der Projektleiter dieser Bibliothek
.Beispielcode:
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));
}
Ausgabe:
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
Eine IP in einem Sub-Netz zu überprüfen, habe ich isInRange Methode in SubnetUtils Klasse. Aber diese Methode hat einen Fehler, wenn Ihr Subnetz ist X, jede IP-Adresse, die niedriger ist als X, isInRange true zurück. Zum Beispiel, wenn Ihr Subnetz war 10.10.30.0/24 und Sie mögen 10.10.20.5 überprüfen, diese Methode true zurück. Um mit diesem Fehler, den ich unten Code verwendet wird.
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;
}
Hier ist eine Version, die mit IPv4 und IPv6 einem mit Präfix und ein mit Netzwerkmaske funktioniert.
/**
* 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;
}
}
Ich weiß, das sehr alte Frage, aber ich gestolpert, als ich war auf der Suche das gleiche Problem zu lösen.
Es gibt commons-ip-math Bibliothek, die ich glaube, eine sehr gut tut Job. Bitte beachten Sie, dass ab Mai 2019 hat es nicht in die Bibliothek alle Updates waren (dass seine bereits sehr ausgereift Bibliothek sein könnte). Seine auf Maven-central
Es unterstützt sowohl IPv4 als auch IPv6-Adressen arbeiten. Ihre kurze Dokumentation hat Beispiele, wie Sie überprüfen können, ob eine Adresse in einem bestimmten Bereich ist IPv4 und IPv6
Beispiel für IPv4 Bereichsprüfung:
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);