¿Cómo extraer la dirección IP en Spring MVC Controller get call?


93

Estoy trabajando en el proyecto del controlador Spring MVC en el que estoy haciendo una llamada GET URL desde el navegador -

A continuación se muestra la URL con la que estoy haciendo una llamada GET desde el navegador:

http://127.0.0.1:8080/testweb/processing?workflow=test&conf=20140324&dc=all

Y a continuación se muestra el código en el que se produce la llamada después de presionar en el navegador:

@RequestMapping(value = "processing", method = RequestMethod.GET)
public @ResponseBody ProcessResponse processData(@RequestParam("workflow") final String workflow,
    @RequestParam("conf") final String value, @RequestParam("dc") final String dc) {

        System.out.println(workflow);
        System.out.println(value);
        System.out.println(dc);

        // some other code
    }

Planteamiento del problema:-

Ahora, ¿hay alguna forma de que pueda extraer la dirección IP de algún encabezado? Lo que significa que me gustaría saber de qué dirección IP viene la llamada, es decir, quienquiera que llame por encima de la URL, necesito saber su dirección IP. ¿Es posible hacer esto?


Intente usar Spring AOP y manejar HttpServletRequest. stackoverflow.com/questions/19271807/…
Dilip G

Respuestas:


148

La solucion es

@RequestMapping(value = "processing", method = RequestMethod.GET)
public @ResponseBody ProcessResponse processData(@RequestParam("workflow") final String workflow,
    @RequestParam("conf") final String value, @RequestParam("dc") final String dc, HttpServletRequest request) {

        System.out.println(workflow);
        System.out.println(value);
        System.out.println(dc);
        System.out.println(request.getRemoteAddr());
        // some other code
    }

Agregue HttpServletRequest requesta la definición de su método y luego use la API de Servlet

Spring Documentation aquí dicho en

15.3.2.3 Argumentos y tipos de retorno de métodos de controlador admitidos

Handler methods that are annotated with @RequestMapping can have very flexible signatures.
Most of them can be used in arbitrary order (see below for more details).

Request or response objects (Servlet API). Choose any specific request or response type,
for example ServletRequest or HttpServletRequest

1
Gracias Koitoer por la ayuda. Una pregunta rápida, suponga que si la llamada proviene de Load Balancer en lugar de una máquina específica, ¿esto también funcionará? Supongo que no ...
john

No, no lo hará, pero hay alguna configuración en el balanceador de carga que puede enviar la IP ya que no existe, probablemente este sea tu caso
Koitoer

Verifique que probablemente el equilibrador de carga pueda enviar esos valores en un encabezado, así que considere usar el método getHeader de HttpServletRequest.
Koitoer

Koitoer ¡¡Funciona perfectamente !! Pero hay otra forma en lugar de HttpServletRequest.
Harshal Patil

1
Esto está desaprobado.
Gewure

112

Llego tarde aquí, pero esto podría ayudar a alguien que busque la respuesta. Normalmente servletRequest.getRemoteAddr()funciona.

En muchos casos, los usuarios de su aplicación pueden estar accediendo a su servidor web a través de un servidor proxy o tal vez su aplicación esté detrás de un equilibrador de carga.

Por lo tanto, debe acceder al encabezado http X-Fordered-For en tal caso para obtener la dirección IP del usuario.

p.ej String ipAddress = request.getHeader("X-FORWARDED-FOR");

Espero que esto ayude.


11
Tenga en cuenta que X-Forwarded-Forgeneralmente es una lista de ips separados por comas, con cada proxy en la cadena agregando la dirección remota que ve a la lista. Entonces, una buena implementación generalmente tendría una lista de proxies confiables y "omitir" esos ips al leer este encabezado de derecha a izquierda.
Raman

cómo obtener la dirección IP como 111.111.111.111/X
Muneeb Mirza

26

Yo uso ese método para hacer esto

public class HttpReqRespUtils {

    private static final String[] IP_HEADER_CANDIDATES = {
        "X-Forwarded-For",
        "Proxy-Client-IP",
        "WL-Proxy-Client-IP",
        "HTTP_X_FORWARDED_FOR",
        "HTTP_X_FORWARDED",
        "HTTP_X_CLUSTER_CLIENT_IP",
        "HTTP_CLIENT_IP",
        "HTTP_FORWARDED_FOR",
        "HTTP_FORWARDED",
        "HTTP_VIA",
        "REMOTE_ADDR"
    };

    public static String getClientIpAddressIfServletRequestExist() {

        if (RequestContextHolder.getRequestAttributes() == null) {
            return "0.0.0.0";
        }

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        for (String header: IP_HEADER_CANDIDATES) {
            String ipList = request.getHeader(header);
            if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) {
                String ip = ipList.split(",")[0];
                return ip;
            }
        }

        return request.getRemoteAddr();
    }
}

1
donde lo uso
Maifee Ul Asad

12

Puede obtener la dirección IP de forma estática de la RequestContextHoldersiguiente manera:

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
        .getRequest();

String ip = request.getRemoteAddr();

4

Pon este método en tu BaseController:

@SuppressWarnings("ConstantConditions")
protected String fetchClientIpAddr() {
    HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.getRequestAttributes())).getRequest();
    String ip = Optional.ofNullable(request.getHeader("X-FORWARDED-FOR")).orElse(request.getRemoteAddr());
    if (ip.equals("0:0:0:0:0:0:0:1")) ip = "127.0.0.1";
    Assert.isTrue(ip.chars().filter($ -> $ == '.').count() == 3, "Illegal IP: " + ip);
    return ip;
}

4

Vea abajo. Este código funciona con spring-boot y spring-boot + apache CXF / SOAP.

    // in your class RequestUtil
    private static final String[] IP_HEADER_NAMES = { 
                                                        "X-Forwarded-For",
                                                        "Proxy-Client-IP",
                                                        "WL-Proxy-Client-IP",
                                                        "HTTP_X_FORWARDED_FOR",
                                                        "HTTP_X_FORWARDED",
                                                        "HTTP_X_CLUSTER_CLIENT_IP",
                                                        "HTTP_CLIENT_IP",
                                                        "HTTP_FORWARDED_FOR",
                                                        "HTTP_FORWARDED",
                                                        "HTTP_VIA",
                                                        "REMOTE_ADDR"
                                                    };

    public static String getRemoteIP(RequestAttributes requestAttributes)
    {
        if (requestAttributes == null)
        {
            return "0.0.0.0";
        }
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String ip = Arrays.asList(IP_HEADER_NAMES)
            .stream()
            .map(request::getHeader)
            .filter(h -> h != null && h.length() != 0 && !"unknown".equalsIgnoreCase(h))
            .map(h -> h.split(",")[0])
            .reduce("", (h1, h2) -> h1 + ":" + h2);
        return ip + request.getRemoteAddr();
    }

    //... in service class:
    String remoteAddress = RequestUtil.getRemoteIP(RequestContextHolder.currentRequestAttributes());

:)


3

A continuación se muestra la forma de Spring, con un autowiredbean de solicitud en la @Controllerclase:

@Autowired 
private HttpServletRequest request;

System.out.println(request.getRemoteHost());

1
Esto podría causar problemas con el uso simultáneo del controlador en varios subprocesos. Solo se deben inyectar singletons en @Controllerinstancias usando @Autowired. De lo contrario, debe usar @Scope(BeanDefinition.SCOPE_PROTOTYPE)en la clase de controlador para asegurarse de que se realice una nueva instancia del controlador con cada solicitud. Esto es menos eficiente, pero es una solución si debe inyectar algo como una propiedad en la clase del controlador.
Andy

1

En mi caso, estaba usando Nginx frente a mi aplicación con la siguiente configuración:

location / {
     proxy_pass        http://localhost:8080/;
     proxy_set_header  X-Real-IP $remote_addr;
     proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header  Host $http_host;
     add_header Content-Security-Policy 'upgrade-insecure-requests';
}

así que en mi aplicación obtengo la IP del usuario real así:

String clientIP = request.getHeader("X-Real-IP");

0
private static final String[] IP_HEADER_CANDIDATES = {
            "X-Forwarded-For",
            "Proxy-Client-IP",
            "WL-Proxy-Client-IP",
            "HTTP_X_FORWARDED_FOR",
            "HTTP_X_FORWARDED",
            "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_CLIENT_IP",
            "HTTP_FORWARDED_FOR",
            "HTTP_FORWARDED",
            "HTTP_VIA",
            "REMOTE_ADDR"
    };

    public static String getIPFromRequest(HttpServletRequest request) {
        String ip = null;
        if (request == null) {
            if (RequestContextHolder.getRequestAttributes() == null) {
                return null;
            }
            request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        }

        try {
            ip = InetAddress.getLocalHost().getHostAddress();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (!StringUtils.isEmpty(ip))
            return ip;

        for (String header : IP_HEADER_CANDIDATES) {
            String ipList = request.getHeader(header);
            if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) {
                return ipList.split(",")[0];
            }
        }

        return request.getRemoteAddr();
    }

Combino el código anterior para que este código funcione en la mayoría de los casos. Pasa lo HttpServletRequest requestque obtienes de la api al método

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.