Comment extraire l'adresse IP dans Spring MVC Controller pour obtenir un appel?

93

Je travaille sur un projet de contrôleur Spring MVC dans lequel je fais un appel GET URL à partir du navigateur -

Vous trouverez ci-dessous l'url par laquelle je passe un appel GET à partir du navigateur -

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

Et ci-dessous est le code dans lequel l'appel intervient après avoir frappé le navigateur -

@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
    }

Énoncé du problème: -

Y a-t-il maintenant un moyen d'extraire l'adresse IP d'un en-tête? Cela signifie que je voudrais savoir à partir de quelle adresse IP, l'appel provient, ce qui signifie que quiconque appelle ci-dessus URL, j'ai besoin de connaître son adresse IP. Est-ce possible?

John
la source
Essayez d'utiliser Spring AOP et de gérer HttpServletRequest. stackoverflow.com/questions/19271807/…
Dilip G

Réponses:

148

La solution est

@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
    }

Ajoutez HttpServletRequest requestà votre définition de méthode, puis utilisez l'API Servlet

Documentation de printemps ici dit dans

15.3.2.3 Arguments de méthode de gestionnaire et types de retour pris en charge

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
Koitoer
la source
1
Merci Koitoer pour l'aide. Une question rapide, supposons que si l'appel provient de Load Balancer au lieu d'une machine spécifique, cela fonctionnera également? Je suppose que non ..
John
Non, ce n'est pas le cas, mais il y a une configuration dans l'équilibreur de charge qui peut envoyer l'IP car elle n'existe pas, c'est probablement votre cas
Koitoer
Vérifiez que l'équilibreur de charge peut probablement envoyer ces valeurs dans un en-tête, pensez donc à utiliser la méthode getHeader de HttpServletRequest.
Koitoer
Koitoer Cela fonctionne parfaitement !! Mais il existe un autre moyen que HttpServletRequest.
Harshal Patil
1
Ceci est obsolète.
Gewure
112

Je suis en retard ici, mais cela pourrait aider quelqu'un à chercher la réponse. Fonctionne généralement servletRequest.getRemoteAddr().

Dans de nombreux cas, les utilisateurs de votre application peuvent accéder à votre serveur Web via un serveur proxy ou peut-être que votre application se trouve derrière un équilibreur de charge.

Vous devez donc accéder à l'en - tête http X-Forwarded-For dans un tel cas pour obtenir l'adresse IP de l'utilisateur.

par exemple String ipAddress = request.getHeader("X-FORWARDED-FOR");

J'espère que cela t'aides.

sunitkatkar
la source
11
Notez qu'il X-Forwarded-Fors'agit généralement d'une liste d'ips séparés par des virgules, chaque proxy de la chaîne ajoutant l'adresse distante qu'il voit à la liste. Ainsi, une bonne implémentation aurait généralement une liste de proxies de confiance et "sauter" ces ips lors de la lecture de cet en-tête de droite à gauche.
Raman
comment obtenir l'adresse IP comme 111.111.111.111/X
Muneeb Mirza
26

J'utilise une telle méthode pour faire ça

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();
    }
}
panser
la source
1
où est-ce que je l'utilise?
Maifee Ul Asad
12

Vous pouvez obtenir l'adresse IP de manière statique RequestContextHoldercomme ci-dessous:

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

String ip = request.getRemoteAddr();
Radouane ROUFID
la source
4

Mettez cette méthode dans votre 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;
}
BaiJiFeiLong
la source
4

Voir ci-dessous. Ce code fonctionne avec spring-boot et 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());

:)

Vagner Nogueira
la source
3

Vous trouverez ci-dessous la méthode Spring, avec autowiredrequest bean en @Controllerclasse:

@Autowired 
private HttpServletRequest request;

System.out.println(request.getRemoteHost());
Léon
la source
1
Cela pourrait entraîner des problèmes d'utilisation simultanée du contrôleur sur plusieurs threads. Seuls les singletons doivent être injectés dans les @Controllerinstances en utilisant @Autowired. Sinon, vous devez utiliser @Scope(BeanDefinition.SCOPE_PROTOTYPE)sur la classe de contrôleur pour vous assurer qu'une nouvelle instance du contrôleur est créée avec chaque requête. Ceci est moins efficace, mais constitue une solution de contournement si vous devez injecter quelque chose en tant que propriété dans la classe de contrôleur.
Andy
1

Dans mon cas, j'utilisais Nginx devant mon application avec la configuration suivante:

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';
}

donc dans mon application, j'obtiens l'IP de l'utilisateur réel comme ceci:

String clientIP = request.getHeader("X-Real-IP");
BaDr Amer
la source
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();
    }

Je combine le code ci-dessus à ce code fonctionne dans la plupart des cas. Transmettez le que HttpServletRequest requestvous obtenez de l'API à la méthode

Kyo Huu
la source