2013-08-07 7 views
9

Ich erhalte Client IP-Adresse über folgenden Methode ermitteln:Java - Wie IP-Version

public static String getClientIpAddr(HttpServletRequest request) { 
    String ip = request.getHeader("X-Forwarded-For"); 
    ... 
    return ip 
} 

Jetzt möchte ich erkennen, ob es sich um eine IPV4 oder IPV6 ist.

+2

Sie regex wie angegeben http://www.java2s.com/Code/Java/Network-Protocol/DetermineifthegivenstringisavalidIPv4orIPv6address hier verwenden können. htm – Tala

+0

Beachten Sie, dass, wenn X-Forwarded-For von einigen Ihrer * Server (wie BigIP F5) festgelegt ist, kann nicht vertraut werden, da es vom Client auf alles gesetzt werden kann. – lapkritinis

Antwort

15

Sie könnten eine InetAddress zu erstellen und prüfen, ob es aber

InetAddress address = InetAddress.getByName(ip); 
if (address instanceof Inet6Address) { 
    // It's ipv6 
} else if (address instanceof Inet4Address) { 
    // It's ipv4 
} 

Es ist ein wenig umständlich erscheint, eine IPv4- oder IPv6-Instanz geworden ist, und ich hoffe, dass es eine bessere Lösung ist.

+0

Besser wie? Es basiert auf dem JDK und nicht auf einem selbstgewachsenen Regex. Scheint OK für mich. – EJP

+2

Besser darin, dass es sich nicht auf instanceof verlässt. Es wäre schön, eine Methode in InetAddress zu haben, die eine Konstante zurückgibt, um die verwendete Version anzuzeigen. – Bex

5

Wenn Sie sicher sind, dass Sie entweder ein IPv4 oder IPv6 erhalten, können Sie Folgendes versuchen. Wenn Sie einen DNS-Namen haben, versucht dies, eine Suche durchzuführen. Wie auch immer, versuchen Sie dies:

try { 

    InetAddress address = InetAddress.getByName(myIpAddr); 

    if (address instanceof Inet4Address) { 
     // your IP is IPv4 
    } else if (address instanceof Inet6Address) { 
     // your IP is IPv6 
    } 

} catch(UnknownHostException e) { 

    // your address was a machine name like a DNS name, and couldn't be found 

} 
+0

Bitte ändern Sie die 'Inet4Address' in' Inet6Address' im 'else' Teil. – tokhi

+0

Fertig, danke dafür – morgano

0

Dank Tala.

Dies ist, was ich von this example mit geringfügigen Änderungen verwendet haben versucht:

private static Pattern VALID_IPV4_PATTERN = null; 
    private static Pattern VALID_IPV6_PATTERN = null; 
    private static final String ipv4Pattern = "(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])"; 
    private static final String ipv6Pattern = "([0-9a-f]{1,4}:){7}([0-9a-f]){1,4}"; 

    static { 
    try { 
     VALID_IPV4_PATTERN = Pattern.compile(ipv4Pattern, Pattern.CASE_INSENSITIVE); 
     VALID_IPV6_PATTERN = Pattern.compile(ipv6Pattern, Pattern.CASE_INSENSITIVE); 
    } catch (PatternSyntaxException e) { 
     //logger.severe("Unable to compile pattern", e); 
    } 
    } 

    public static String isIpAddressV4orV6(String ipAddress) { 

     Matcher ipv4 = IP_Utilities.VALID_IPV4_PATTERN.matcher(ipAddress); 
     if (ipv4.matches()) { 
      return "IPV4"; 
     } 
     Matcher ipv6 = IP_Utilities.VALID_IPV6_PATTERN.matcher(ipAddress); 
     if (ipv6.matches()) { 
       return "IPV6"; 
     } 
     return ""; 
    } 
+0

Verwenden Sie nicht Ihre eigene Regex dafür. Verwenden Sie die Instanz der Lösung. – EJP

+1

Danke, ja 'instanceof' ist effizienter. – tokhi

+2

Ich habe nichts über Effizienz gesagt. Es ist mehr * korrekt *, weil es in das JDK integriert ist und kein eigener Code ist. – EJP