web-dev-qa-db-fra.com

Obtenez une véritable adresse IP client dans un servlet

J'ai des problèmes avec un problème simple. Je voudrais obtenir l'IP client réel à l'intérieur d'un HTTPServlet .

Depuis, j'ai utilisé:

request.getRemoteAddr()

Mais maintenant, il renvoie une fausse adresse IP. par exemple: xxx.xxx.xxx. 50 mais mon IP est quelque chose comme xxx.xxx.xxx. 159 . (vérifié sur http://whatismyipaddress.com/ ).

Maintenant, j'ai essayé d'utiliser:

request.getHeader("X-Forwarded-For")

Il renvoie NULL.

J'ai également pris une sonde avec la classe suivante:

public class IpUtils {

public static final String _255 = "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
public static final Pattern pattern = Pattern.compile("^(?:" + _255 + "\\.){3}" + _255 + "$");

public static String longToIpV4(long longIp) {
    int octet3 = (int) ((longIp >> 24) % 256);
    int octet2 = (int) ((longIp >> 16) % 256);
    int octet1 = (int) ((longIp >> 8) % 256);
    int octet0 = (int) ((longIp) % 256);

    return octet3 + "." + octet2 + "." + octet1 + "." + octet0;
}

public static long ipV4ToLong(String ip) {
    String[] octets = ip.split("\\.");
    return (Long.parseLong(octets[0]) << 24) + (Integer.parseInt(octets[1]) << 16)
            + (Integer.parseInt(octets[2]) << 8) + Integer.parseInt(octets[3]);
}

public static boolean isIPv4Private(String ip) {
    long longIp = ipV4ToLong(ip);
    return (longIp >= ipV4ToLong("10.0.0.0") && longIp <= ipV4ToLong("10.255.255.255"))
            || (longIp >= ipV4ToLong("172.16.0.0") && longIp <= ipV4ToLong("172.31.255.255"))
            || longIp >= ipV4ToLong("192.168.0.0") && longIp <= ipV4ToLong("192.168.255.255");
}

public static boolean isIPv4Valid(String ip) {
    return pattern.matcher(ip).matches();
}

public static String getIpFromRequest(HttpServletRequest request) {
    String ip;
    boolean found = false;
    if ((ip = request.getHeader("x-forwarded-for")) != null) {
        StringTokenizer tokenizer = new StringTokenizer(ip, ",");
        while (tokenizer.hasMoreTokens()) {
            ip = tokenizer.nextToken().trim();
            if (isIPv4Valid(ip) && !isIPv4Private(ip)) {
                found = true;
                break;
            }
        }
    }

    if (!found) {
        ip = request.getRemoteAddr();
    }

    return ip;
}
}

Il a également renvoyé l'IP xxx.xxx.xxx.50. :(

Maintenant, je ne sais pas comment obtenir la véritable adresse IP du client. Si quelqu'un connaît la solution, veuillez répondre.

33
TAR515

Je suppose que votre problème est que vous exécutez le serveur quelque part dans le réseau local, donc vous obtenez votre IP dans ce réseau. Cependant, lorsque vous essayez d'utiliser un service en ligne qui découvre votre adresse IP, votre IP est l'IP du routeur de votre fournisseur de services ou quelque chose comme ça. L'utilisation de request.getRemoteAddr() est correcte. C'est ce que font ces services et ils n'ont pas d'autres installations.

31
AlexR

Lorsque vous avez un périphérique NAT (traduction d'adresse réseau) avant votre conteneur de servlet request.getRemoteAddr() renvoie l'adresse de NAT, car il lance une nouvelle connexion.

Pour résoudre votre problème, vous devez vous configurer NAT pour envoyer dans un en-tête l'adresse IP du client d'origine. Ensuite, pour prendre l'en-tête de la demande. Dans le cas où vous configurez dans NAT En-tête X-Forwarded-For utilisez ce code: request.getHeader("X-Forwarded-For")

Votre fonction est correcte, vous pouvez l'utiliser lorsque vous configurez NAT.

12
Michael

Java

String ip = request.getRemoteAddr();
if (ip.equalsIgnoreCase("0:0:0:0:0:0:0:1")) {
    InetAddress inetAddress = InetAddress.getLocalHost();
    String ipAddress = inetAddress.getHostAddress();
    ip = ipAddress;
}
model.addAttribute("IP", ip);

JSP <span><B>IP : <c:out value="${IP}" /></B></span> // Spring MAV

[~ # ~] jsp [~ # ~]

<%@ page language="Java" contentType="text/html; charset=ISO-8859-1"   pageEncoding="ISO-8859-1"%>
<%@ page import="Java.net.InetAddress" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Displays Client IP Address</title>
</head>
<body>
<%
    // paste above Java code 
out.println("<br><B>Clients IP : </B>"+ip);
%>
<span><br>Local Host  : <%= request.getRemoteAddr() %></span>
<span><br>ServerPort  : <%= request.getServerPort() %></span>
<span><br>Path        : <%= request.getRequestURI()%></span>
</span>
</body>
</html>

Si le jsp est déployé sur le serveur local et que l'accès à ce jsp renvoie 0: 0: 0: 0: 0: 0: 0: 1. Si vous accédez à l'application localement avec ip, cela retourne IP.

RESTful Services Web avec Jersey

@javax.ws.rs.Path("/ip")
public class GetIPInfo {

    @GET    @Produces(MediaType.TEXT_PLAIN) 
    public Response getIP(@Context javax.servlet.http.HttpServletRequest request) throws UnknownHostException { 

        String remoteHost = request.getRemoteHost();
        String remoteAddr = request.getRemoteAddr();
        if (remoteAddr.equals("0:0:0:0:0:0:0:1")) {
            InetAddress localip = Java.net.InetAddress.getLocalHost();
            remoteAddr = localip.getHostAddress();
            remoteHost = localip.getHostName();
        }
        int remotePort = request.getRemotePort();

        String msgoutput = remoteHost + " (" + remoteAddr + " : " + remotePort + ")";
        return Response.status(200).entity(msgoutput).build(); 
    }
}

en utilisant JavaScript pour trouver IP

10
Yash