स्प्रिंग एमवीसी कंट्रोलर कॉल में आईपी एड्रेस कैसे निकाले?


94

मैं स्प्रिंग एमवीसी नियंत्रक परियोजना पर काम कर रहा हूं जिसमें मैं ब्राउज़र से जीईटी यूआरएल कॉल कर रहा हूं -

नीचे url है जिसके द्वारा मैं ब्राउज़र से GET कॉल कर रहा हूं -

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

और नीचे वह कोड है जिसमें ब्राउज़र पर मारने के बाद कॉल आता है -

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

समस्या का विवरण:-

अब कोई रास्ता है, मैं कुछ हेडर से आईपी एड्रेस निकाल सकता हूं? मतलब मैं जानना चाहूंगा कि कौन सा IP पता, कॉल आ रहा है, मतलब जो कोई भी URL से ऊपर कॉल कर रहा है, मुझे उनका IP पता जानना होगा। क्या ऐसा करना संभव है?


स्प्रिंग AOP का उपयोग करने और HttpServletRequest को संभालने का प्रयास करें। stackoverflow.com/questions/19271807/…
दिलीप जी

जवाबों:


153

उपाय है

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

HttpServletRequest requestअपनी विधि परिभाषा में जोड़ें और फिर सर्वलेट एपीआई का उपयोग करें

स्प्रिंग प्रलेखन यहाँ में कहा

15.3.2.3 समर्थित हैंडलर विधि तर्क और वापसी प्रकार

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
मदद के लिए धन्यवाद Koitoer। एक त्वरित प्रश्न, मान लें कि यदि कॉल विशिष्ट मशीन के बजाय लोड बैलेंसर से आ रही है तो यह भी काम करेगा? मुझे नहीं लगता ..
जॉन

नहीं, यह अभ्यस्त नहीं है, लेकिन लोडबॉलर में कुछ कॉन्फ़िगरेशन हैं जो आईपी भेज सकते हैं क्योंकि वे मौजूद नहीं हैं, शायद यह आपका मामला है
कोइटोइर

संभवतया चेक करें कि बैलेंसर उन मानों को हेडर में भेज सकता है, इसलिए HttpServletRequest के गेटहेडर विधि का उपयोग करने पर विचार करें।
कोइटोइर

Koitoer यह पूरी तरह से काम करता है !! लेकिन HttpServletRequest के बजाय कोई अन्य तरीका है।
हर्षल पाटिल

1
यह पदावनत है।
Gewure

114

मुझे यहाँ देर हो रही है, लेकिन इससे किसी को उत्तर की तलाश में मदद मिल सकती है। आमतौर पर servletRequest.getRemoteAddr()काम करता है।

कई मामलों में आपके एप्लिकेशन उपयोगकर्ता प्रॉक्सी सर्वर के माध्यम से आपके वेब सर्वर तक पहुंच सकते हैं या हो सकता है कि आपका एप्लिकेशन लोड बैलेंसर के पीछे हो।

इसलिए आपको उपयोगकर्ता के आईपी पते को प्राप्त करने के लिए ऐसे मामले में एक्स-फॉरवर्डेड-फॉर http हेडर का उपयोग करना चाहिए ।

जैसे String ipAddress = request.getHeader("X-FORWARDED-FOR");

उम्मीद है की यह मदद करेगा।


11
ध्यान दें कि X-Forwarded-Forआम तौर पर ips की अल्पविराम से अलग की गई सूची होती है, श्रृंखला में प्रत्येक प्रॉक्सी के साथ रिमोट पता जो सूची में दिखता है उसे जोड़ते हैं। इसलिए एक अच्छा कार्यान्वयन आमतौर पर विश्वसनीय शीर्षकों की एक सूची होगी और दाएं से बाएं इस हेडर को पढ़ते समय उन ips को "स्किप" करें।
रमन

111.111.111.111/X के रूप में आईपी पता कैसे प्राप्त करें
मुनिब मिर्जा

ध्यान दें कि जैसे बिलाव है RemoteIpValveकि पार्स X-Forwarded-Forशीर्ष लेख और यह सेट पर HttpServletRequest, ताकि servletRequest.getRemoteAddr()रिटर्न सही अंत उपयोगकर्ता आईपी पते। स्प्रिंग बूट में इसे server.tomcat.remote-ip-header=X-Forwarded-Forएप्लिकेशन प्रॉपर्टी के माध्यम से सक्षम किया जा सकता है
Gediminas Rimsa

26

मैं ऐसा करने के लिए इस तरह की विधि का उपयोग करता हूं

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
मैं इसका उपयोग कहां करूं?
मैफ़ी उल असद

12

आप RequestContextHolderनीचे दिए गए विवरणों से IP पता प्राप्त कर सकते हैं :

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

String ip = request.getRemoteAddr();

4

इस विधि को अपने 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

निचे देखो। यह कोड स्प्रिंग-बूट और स्प्रिंग-बूट + अपाचे 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

कक्षा autowiredमें अनुरोध बीन के साथ नीचे स्प्रिंग तरीका है @Controller:

@Autowired 
private HttpServletRequest request;

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

1
यह कई धागों में नियंत्रक के समवर्ती उपयोग के साथ समस्या पैदा कर सकता है। केवल एकल @Controllerका उपयोग कर उदाहरणों में इंजेक्ट किया जाना चाहिए @Autowired। अन्यथा, आपको यह @Scope(BeanDefinition.SCOPE_PROTOTYPE)सुनिश्चित करने के लिए नियंत्रक वर्ग पर उपयोग करना होगा कि नियंत्रक का एक नया उदाहरण हर अनुरोध के साथ बनाया गया है। यह कम कुशल है, लेकिन यदि आप नियंत्रक वर्ग के लिए एक संपत्ति के रूप में कुछ इंजेक्षन करना चाहते हैं तो यह एक समाधान है।
एंडी

1

मेरे मामले में, मैं निम्नलिखित कॉन्फ़िगरेशन के साथ अपने आवेदन के सामने Nginx का उपयोग कर रहा था:

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

इसलिए मेरे आवेदन में मुझे वास्तविक उपयोगकर्ता आईपी मिलता है जैसे:

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

मैं इस कोड के ऊपर दिए गए कोड को ज्यादातर मामले के लिए काम करता हूं। पास HttpServletRequest requestआप api से विधि के लिए मिलता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.