Spring MVC Controller'da IP Adresi nasıl alınır aranır?


93

Tarayıcıdan bir GET URL çağrısı yaptığım Spring MVC denetleyici projesi üzerinde çalışıyorum -

Aşağıda, tarayıcıdan GET araması yaptığım url var -

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

Tarayıcıya tıkladıktan sonra aramanın geldiği kod aşağıdadır -

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

Sorun bildirimi:-

Şimdi herhangi bir yol var mı, bazı başlıklardan IP Adresini çıkarabilir miyim? Yani hangi IP adresinden aramanın geldiğini bilmek istiyorum, yani yukarıdaki URL'yi arayan her kimse IP Adresini bilmem gerekiyor. Bunu yapmak mümkün mü?


Spring AOP kullanmayı ve HttpServletRequest'i işlemeyi deneyin. stackoverflow.com/questions/19271807/…
Dilip G

Yanıtlar:


148

Çözüm şudur

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

Ekle HttpServletRequest requestYöntem tanımınıza ve ardından Servlet API'sini kullanın

Bahar Dokümantasyonu burada dedi

15.3.2.3 Desteklenen işleyici yöntemi bağımsız değişkenleri ve dönüş türleri

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
Yardım için teşekkürler Koitoer. Hızlı bir soru, varsayalım ki arama belirli bir makine yerine Load Balancer'dan geliyorsa bu da işe yarayacak mı? Sanırım değil ..
John

Hayır, olmayacak, ancak
yük dengeleyicide

Yük dengeleyicinin bu değerleri bir başlığa gönderebileceğini kontrol edin, bu nedenle HttpServletRequest'in getHeader yöntemini kullanmayı düşünün.
Koitoer

Koitoer Mükemmel çalışıyor !! Ancak HttpServletRequest dışında başka bir yol var.
Harhal Patil

1
Bu kullanımdan kaldırılmıştır.
Gewure

112

Buraya geç kaldım, ama bu birisinin cevabı aramasına yardımcı olabilir. TipikservletRequest.getRemoteAddr() işe yarar.

Çoğu durumda, uygulama kullanıcılarınız web sunucunuza bir proxy sunucusu aracılığıyla erişiyor olabilir veya uygulamanız bir yük dengeleyicinin arkasında olabilir.

Dolayısıyla, X-Forwarded-For'a erişmelisiniz , böyle bir durumda kullanıcının IP adresini almak için http başlığına .

Örneğin String ipAddress = request.getHeader("X-FORWARDED-FOR");

Bu yardımcı olur umarım.


11
Not X-Forwarded-Forlistede görür uzak adres ilave zincirdeki her proxy ile, genel olarak ıp virgülle ayrılmış bir listesidir. Dolayısıyla, iyi bir uygulama genellikle güvenilir proxy'lerin bir listesine sahip olur ve bu başlığı sağdan sola okurken bu ips'leri "atlar".
Raman

111.111.111.111/X olarak ip adresi nasıl alınır
Muneeb Mirza

26

Bunu yapmak için böyle bir yöntem kullanıyorum

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
onu nerede kullanırım?
Maifee Ul Asad

12

IP adresini RequestContextHolderaşağıdaki şekilde statik olarak alabilirsiniz :

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

String ip = request.getRemoteAddr();

4

Bu yöntemi BaseController cihazınıza koyun:

@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

Aşağıya bakınız. Bu kod, yay önyükleme ve yay önyükleme + apache CXF / SOAP ile çalışır.

    // 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

Sınıfta autowiredtalep fasulyesi ile Bahar yolu aşağıdadır @Controller:

@Autowired 
private HttpServletRequest request;

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

1
Bu, denetleyicinin birden çok iş parçacığında eşzamanlı kullanımıyla ilgili sorunlara neden olabilir. Kullanılarak @Controllerörneklere sadece tekil enjekte edilmelidir @Autowired. Aksi takdirde, @Scope(BeanDefinition.SCOPE_PROTOTYPE)her talepte yeni bir denetleyici örneğinin yapılmasını sağlamak için denetleyici sınıfında kullanmanız gerekir . Bu daha az verimlidir, ancak denetleyici sınıfına bir özellik olarak bir şey eklemeniz gerekiyorsa geçici bir çözümdür.
Andy

1

Benim durumumda, aşağıdaki yapılandırmayla uygulamamın önünde Nginx kullanıyordum:

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

bu yüzden uygulamamda gerçek kullanıcı ipini şu şekilde alıyorum:

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();
    }

Çoğu durumda yukarıdaki kodu bu kod çalışmasıyla birleştiriyorum. Geçiren HttpServletRequest requestEğer yönteme API aldığım

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.