Laravel 5+ में क्लाइंट IP पता कैसे प्राप्त करें


136

मैं लारवेल में ग्राहक का आईपी पता प्राप्त करने की कोशिश कर रहा हूं।

PHP का उपयोग करके क्लाइंट का IP प्राप्त करना आसान है $_SERVER["REMOTE_ADDR"]। यह कोर PHP में ठीक काम कर रहा है, लेकिन जब मैं Laravel में एक ही चीज़ का उपयोग करता हूं, तो यह विज़िटर के IP के बजाय सर्वर IP लौटाता है।

जवाबों:


194

लारवेल एपीआई को देखते हुए :

Request::ip();

आंतरिक रूप से, यह सिम्फनी अनुरोध ऑब्जेक्टgetClientIps से विधि का उपयोग करता है :

public function getClientIps()
{
    $clientIps = array();
    $ip = $this->server->get('REMOTE_ADDR');
    if (!$this->isFromTrustedProxy()) {
        return array($ip);
    }
    if (self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) {
        $forwardedHeader = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
        preg_match_all('{(for)=("?\[?)([a-z0-9\.:_\-/]*)}', $forwardedHeader, $matches);
        $clientIps = $matches[3];
    } elseif (self::$trustedHeaders[self::HEADER_CLIENT_IP] && $this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) {
        $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
    }
    $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from
    $ip = $clientIps[0]; // Fallback to this when the client IP falls into the range of trusted proxies
    foreach ($clientIps as $key => $clientIp) {
        // Remove port (unfortunately, it does happen)
        if (preg_match('{((?:\d+\.){3}\d+)\:\d+}', $clientIp, $match)) {
            $clientIps[$key] = $clientIp = $match[1];
        }
        if (IpUtils::checkIp($clientIp, self::$trustedProxies)) {
            unset($clientIps[$key]);
        }
    }
    // Now the IP chain contains only untrusted proxies and the client IP
    return $clientIps ? array_reverse($clientIps) : array($ip);
} 

3
अनुरोध ऑब्जेक्ट का उपयोग करना मेरे लिए काम नहीं करता है, यह मेरे होमस्टेड सर्वर का पता देता है। 192.168.10.10 जो जाहिर तौर पर मेरा आईपी पता नहीं है।
विंस क्रोनलिन

@VinceKronlein अपने मामले के लिए इस उत्तर को देखें stackoverflow.com/a/41769505/3437790
सेबस्टियन होरिन

3
@VinceKronlein आपके मामले में यह बहुत सही था। चूँकि आप अपने LOCAL नेटवर्क में होमस्टेड को एक्सेस कर रहे थे, आपके पास 192 था। IP। यदि आप इंटरनेट के माध्यम से किसी और के होमस्टेड सर्वर तक पहुंच रहे थे, तो आपका आईपी आपके आईएसपी के माध्यम से बाहर निकल जाएगा और आपका सार्वजनिक उपयोग किया जाएगा।
ied3vil

83

यदि आप एक लोड बैलेंसर के अधीन हैं, तो लारवेल \Request::ip() हमेशा बैलेंसर का आईपी लौटाता है:

            echo $request->ip();
            // server ip

            echo \Request::ip();
            // server ip

            echo \request()->ip();
            // server ip

            echo $this->getIp(); //see the method below
            // clent ip

यह कस्टम विधि असली क्लाइंट आईपी लौटाती है:

public function getIp(){
    foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key){
        if (array_key_exists($key, $_SERVER) === true){
            foreach (explode(',', $_SERVER[$key]) as $ip){
                $ip = trim($ip); // just to be safe
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
                    return $ip;
                }
            }
        }
    }
}

इसके अतिरिक्त, मेरा सुझाव है कि आप लारवेल के थ्रोटल मिडलवेयर का उपयोग करते हुए बहुत सावधान रहें : इसमें लारवेल का उपयोग किया गया है Request::ip(), इसलिए आपके सभी आगंतुकों को एक ही उपयोगकर्ता के रूप में पहचाना जाएगा और आप थ्रॉटल सीमा को बहुत तेज़ी से मारेंगे। मैंने इस लाइव का अनुभव किया और इससे बड़े मुद्दे पैदा हुए।

इसे ठीक करने के लिए:

रोशन \ http \ Request.php

    public function ip()
    {
        //return $this->getClientIp(); //original method
        return $this->getIp(); // the above method
    }

अब आप भी उपयोग कर सकते हैं Request::ip(), जो उत्पादन में वास्तविक आईपी वापस करना चाहिए।


1
सही है अगर (फ़िल्टर_वर ...) दूसरे फॉरच्यू के अंदर? इस कोड को कभी भी निष्पादित नहीं किया जाएगा।
मिस्त्रे83

@ Mistre83 हाँ, आप सही हैं, मुझे लगता है कि यह एक परीक्षा है। मैं इसे अपडेट करता हूं!
सेबस्टियन होरिन

6
यह वास्तव में लार्वा 5.4 के साथ काम करता है। कृपया गीथब पर पीआर बनाने पर विचार करें। मुझे लगता है कि यह डिफ़ॉल्ट व्यवहार होना चाहिए
क्रिस्टल

1
इसने लारावेल 5.3 में एक उपचार किया जब
लारवेल

3
खिचड़ी भाषा आप इसे भरोसेमंद परदेसी के साथ ठीक कर सकते हैं? - laravel.com/docs/master/requests#configuring-trusted-proxies
user2722667

74

का उपयोग करें request()->ip()

लारवेल 5 के बाद से मुझे जो समझ में आया है, यह सलाह दी जाती है कि वैश्विक कार्यों का उपयोग करने के लिए अच्छा अभ्यास करें:

response()->json($v);
view('path.to.blade');
redirect();
route();
cookie();

और, अगर कुछ भी, स्थिर संकेतन के बजाय फ़ंक्शन का उपयोग करते समय मेरी आईडीई क्रिसमस के पेड़ की तरह प्रकाश नहीं करता है।


3
आप सही हैं कि requestएक "वैश्विक" फ़ंक्शन है - यह लार्वा द्वारा प्रदान किए गए वैश्विक सहायक कार्यों में से एक है। हालांकि, अनुरोध मुखौटा, स्थिर नहीं है (और न ही विधि आईपी है) - request()->foo, और Reqest::fooऔर $request->fooसब समान हैं। इस उदाहरण पर एक नज़र डालें: gist.github.com/cjke/026e3036c6a10c672dc5
क्रिस

1
पर्याप्त रूप से उचित - दोनों समान रूप से सही हैं। मैंने अभी सोचा था कि आपने कहाँ कहा "यह Request::ipभ्रामक नहीं हो सकता है
क्रिस

3
समस्या यह है कि ये वैश्विक कार्य आसानी से परीक्षण योग्य नहीं हैं - इनका मजाक नहीं उड़ाया जा सकता। फॉकेड हो सकते हैं। मैं वैश्विक कार्यों से बचने की कोशिश करता हूं, क्योंकि इसका मतलब है कि वैश्विक फ़ंक्शन स्रोत के माध्यम से इसकी कॉल को मॉक करना, जो अतिरिक्त काम है, कष्टप्रद है, और मेरी जिम्मेदारी नहीं होनी चाहिए।
हैकर

1
हालांकि request()->ip()यह सही है, आसपास का पाठ वास्तव में भ्रामक है - विशेष रूप से कहने के लिए "यह नहीं है Request::ip
क्रिस

1
@ क्रिस धन्यवाद, आप बिल्कुल सही कह रहे हैं। स्पष्टता के लिए संपादित!
स्टेन स्मल्डर्स

27

नाम स्थान जोड़ें

use Request;

फिर फ़ंक्शन को कॉल करें

Request::ip();

1
यदि आपके पास नाम स्थान का उपयोग किया है: -> इल्युमिनेट \ Http \ Request का उपयोग करें; बोल्ड अनुरोध के बाद से दोनों संघर्ष के लिए नाम बदलें नाम स्थान
शालिनी

मूल उत्तर सही है। आपको आयात करने की आवश्यकता है use Requestक्योंकि आप मुखौटा का उपयोग करने का प्रयास कर रहे हैं। आपके द्वारा प्रदान किया गया नामस्थान अंतर्निहित वर्ग के लिए है। यदि आप आयात करते हैं कि आपको एक त्रुटि मिलेगी क्योंकि ip()इसे स्टेटिक रूप से नहीं कहा जा सकता है, तो यह है कि मुखौटा क्या है।
jfadich

यदि आप कक्षा को आयात करने से परेशान हैं, तो आपको वास्तविक दोष का उपयोग करना चाहिए, न कि उपनाम use Illuminate\Support\Facades\Request:। यदि नहीं, तो बस उपयोग करें \Request::
हैकर

18

Laravel 5 के लिए आप अनुरोध ऑब्जेक्ट का उपयोग कर सकते हैं। बस इसकी ip()विधि, कुछ इस तरह से कॉल करें :

$request->ip();


12

देखभाल करने के लिए दो चीजें हैं:

  1. एक सहायक फ़ंक्शन प्राप्त करें जो एक रिटर्न देता है Illuminate\Http\Requestऔर ->ip()विधि को कॉल करता है:

    request()->ip();
  2. अपने सर्वर कॉन्फ़िगरेशन के बारे में सोचें, यह प्रॉक्सी का उपयोग कर सकता है या load-balancerविशेष रूप से AWS ELB कॉन्फ़िगरेशन में।

यदि यह आपका मामला है, तो आपको " कॉन्फ़िगर किए गए भरोसेमंद प्रॉक्सीज़ " का पालन करना होगा या शायद "ट्रस्टिंग ऑल प्रोक्सीज़" विकल्प भी सेट करना होगा।

क्यों? क्योंकि आपका सर्वर होने के load-balancerबजाय आपका प्रॉक्सी / आईपी ​​प्राप्त होगा।

यदि आप AWS बैलेंस-लोडर पर हैं, App\Http\Middleware\TrustProxiesतो $proxiesइस तरह से घोषणा करें और घोषणा करें:

protected $proxies = '*';

अब इसका परीक्षण करें और जश्न मनाएं क्योंकि आपने खुद को थ्रॉटल मिडलवेयर से परेशान होने से बचाया था। यह request()->ip()"TrustProxies" को स्थापित किए बिना भी निर्भर करता है , आप अपने सभी उपयोगकर्ताओं को केवल अपराधी के आईपी को अवरुद्ध करने के बजाय लॉगिंग से अवरुद्ध कर सकते हैं।

और क्योंकि थ्रॉटल मिडलवेयर को डॉक्यूमेंटेशन में ठीक से नहीं समझाया गया है, मैं सलाह देता हूं कि " लार्वा 5.2 ट्यूटोरियल फॉर बिगिनर, एपीआई रेट एडिटिंग "

Laravel 5.7 में परीक्षण किया गया


7

Laravel 5.4 में हम आईपी स्टैटिक नहीं कह सकते। उपयोगकर्ता का आईपी पाने का यह एक सही तरीका है:

 use Illuminate\Http\Request;

public function contactUS(Request $request)
    {
        echo $request->ip();
        return view('page.contactUS');
    }

7

यदि आप इस फ़ंक्शन को कॉल करते हैं तो आपको क्लाइंट का आईपी पता आसानी से मिल जाएगा। मैंने पहले से ही अपने मौजूदा प्रोजेक्ट में इसका उपयोग किया है:

public function getUserIpAddr(){
       $ipaddress = '';
       if (isset($_SERVER['HTTP_CLIENT_IP']))
           $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
       else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
           $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
       else if(isset($_SERVER['HTTP_X_FORWARDED']))
           $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
       else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
           $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
       else if(isset($_SERVER['HTTP_FORWARDED']))
           $ipaddress = $_SERVER['HTTP_FORWARDED'];
       else if(isset($_SERVER['REMOTE_ADDR']))
           $ipaddress = $_SERVER['REMOTE_ADDR'];
       else
           $ipaddress = 'UNKNOWN';    
       return $ipaddress;
    }

5

यदि आप अभी भी आईपी के रूप में 127.0.0.1 प्राप्त कर रहे हैं, तो आपको अपना "प्रॉक्सी" जोड़ने की आवश्यकता है, लेकिन ध्यान रखें कि उत्पादन में जाने से पहले आपको इसे बदलना होगा!

पढ़ें " भरोसेमंद प्रॉक्सी को कॉन्फ़िगर करना "।

और इसे जोड़ें:

class TrustProxies extends Middleware
{
    /**
     * The trusted proxies for this application.
     *
     * @var array
     */
    protected $proxies = '*';

अब request()->ip()आपको सही IP देता है।


4

यदि आप क्लाइंट आईपी चाहते हैं और आपका सर्वर एल्ब एल्ब के पीछे है, तो निम्न कोड को यूजर करें। लार्वा 5.3 के लिए परीक्षण किया गया

$elbSubnet = '172.31.0.0/16';
Request::setTrustedProxies([$elbSubnet]);
$clientIp = $request->ip();

1
अब काम नहीं कर रहा है, अब "विश्वसनीय हैडरसेट" नियेड है
शाद्रिक्स

"हाल के" लार्वाल संस्करणों के लिए, डॉक्स laravel.com/docs/5.5/requests#configuring-trusted-proxies
सैंड्रा

0

अगर आपके पास CDN + Load Balancer की तरह ही कई लेयर प्रॉक्सी हैं।
लारवेल रिक्वेस्ट :: आईपी () फ़ंक्शन का उपयोग करके राइट-मोस्ट प्रॉक्सी आईपी मिलेगा, लेकिन क्लाइंट आईपी नहीं।
आप निम्नलिखित समाधान की कोशिश कर सकते हैं।

एप्लिकेशन / HTTP / मिडिलवेयर / TrustProxies.php

protected $proxies = ['0.0.0.0/0'];

संदर्भ: https://github.com/fideloper/TrustedProxy/issues/107#issuecomment-373765215


0

मैंने सेबस्टियन होरिन फंक्शन getIp और रिक्वेस्ट () -> ip () (ग्लोबल रिक्वेस्ट पर) का इस्तेमाल किया, क्योंकि लोकलहोस्ट getIp फंक्शन रिटर्न नल:

$this->getIp() ?? request()->ip();

GetIp फ़ंक्शन:

public function getIp(){
foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key){
    if (array_key_exists($key, $_SERVER) === true){
        foreach (explode(',', $_SERVER[$key]) as $ip){
            $ip = trim($ip); // just to be safe
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
                return $ip;
            }
        }
    }
}

}



-2
  $ip = $_SERVER['REMOTE_ADDR'];

1
यदि आप स्पष्टीकरण की आपूर्ति करते हैं तो यह अधिक मदद करता है कि यह पसंदीदा समाधान क्यों है और बताएं कि यह कैसे काम करता है। हम शिक्षित करना चाहते हैं, न कि केवल कोड प्रदान करना। जैसा कि, सिस्टम इसे निम्न-गुणवत्ता के रूप में चिह्नित कर रहा है, इसलिए इसे सुधारने का प्रयास करें।
को टिन मैन

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