Laravel 5 + 'da istemci IP adresi nasıl alınır


136

Laravel'de müşterinin IP adresini almaya çalışıyorum.

Kullanarak PHP'de bir istemcinin IP'sini almak kolaydır $_SERVER["REMOTE_ADDR"]. Çekirdek PHP'de iyi çalışıyor, ancak Laravel'de aynı şeyi kullandığımda, ziyaretçinin IP'si yerine sunucu IP'sini döndürüyor.

Yanıtlar:


195

Laravel API'ye bakıldığında :

Request::ip();

Dahili olarak, Symfony İstek NesnesindekigetClientIps yöntemi kullanır :

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
İstek nesnesini kullanmak benim için çalışmıyor, Homestead sunucumun adresini döndürüyor. Açıkçası IP adresim olmayan 192.168.10.10.
Vince Kronlein

Durumunuz için @VinceKronlein bu yanıtı kontrol edin stackoverflow.com/a/41769505/3437790
Sebastien Horin

3
@VinceKronlein senin durumunda çok doğruydu. Homestead'e eriştiğiniz için, LOCAL ağınızda, tje 192. IP'ye sahipsiniz. eğer başka birinin ev sunucusuna internet üzerinden erişiyor olsaydınız, IP'niz ISS'nizden geçer ve sizin genel IP adresiniz kullanılırdı.
ied3vil

83

Bir yük dengeleyici altındaysanız, Laravel \Request::ip() her zaman dengeleyicinin IP'sini döndürür:

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

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

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

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

Bu özel yöntem gerçek istemci ipini döndürür:

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

Buna ek olarak Laravel'in gaz ara yazılımını kullanırken çok dikkatli olmanızı öneririm : Laravel'in Request::ip()de kullandığı , böylece tüm ziyaretçileriniz aynı kullanıcı olarak tanımlanacak ve gaz limitine çok hızlı bir şekilde ulaşacaksınız. Bunu canlı olarak yaşadım ve bu büyük sorunlara neden oldu.

Bunu düzeltmek için:

Aydınlatmak \ Http \ Request.php

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

Artık Request::ip()üretimde gerçek IP'yi döndürecek olanı da kullanabilirsiniz .


1
ikinci foreach içindeki if (filter_var ...) doğru mu? bu kod asla çalıştırılmayacaktır.
Mistre83

@ Mistre83 Evet haklısınız, bunun bir test gözetimi olduğunu düşünüyorum. Ben güncelliyorum!
Sebastien Horin

6
bu aslında laravel 5.4 ile çalışır. Lütfen github'da PR yapmayı düşünün. Bunun varsayılan davranış olması gerektiğini düşünüyorum
Crystal

1
Laravel istek nesnenin ip () metodu 127.0.0.1 dönen tuttu bu laravel 5.3 bir tedavi çalıştı
w5m

3
Bunu güvenilir proxy'lerle düzeltemez misin? - laravel.com/docs/master/requests#configuring-trusted-proxies
user2722667

74

Kullanın request()->ip().

Anladığım kadarıyla, Laravel 5'ten beri aşağıdaki gibi küresel işlevleri kullanmak tavsiye edilir / iyi uygulama:

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

Ve eğer bir şey varsa, statik gösterim yerine işlevleri kullanırken IDE'm bir Noel ağacı gibi yanmıyor.


3
Haklısınız, bu request"global" bir fonksiyondur - bu laravel tarafından sağlanan global yardımcı fonksiyonlardan biridir. Ancak, talep cephe statik değil (ne yöntem ip olduğu) - request()->foove Reqest::foove $request->footüm aynıdır. Bir örnek için bu öze
Chris

1
Yeterince adil - her ikisi de eşit derecede doğru. " Request::ipYanıltıcı olmayabilir " dediğin kısmı düşündüm
Chris

3
Sorun şu ki, bu küresel işlevler kolayca test edilemez - alay edilemezler. Cepheler olabilir. Küresel işlevlerden kaçınmaya çalışıyorum çünkü bu, çağrılarıyla dalga geçmek için küresel işlev kaynağına ulaşmak anlamına geliyor, bu ekstra iş, can sıkıcı ve benim sorumluluğum olmamalı.
hackel

1
request()->ip()Doğru olmasına rağmen , çevreleyen metin gerçekten yanıltıcıdır - özellikle "öyle değil Request::ip.
Chris

1
@Chris Teşekkürler, kesinlikle haklısınız. Netlik için düzenlendi!
Stan Smulders

27

Ad alanı ekleyin

use Request;

Ardından işlevi çağırın

Request::ip();

1
Ad alanı kullanıyorsanız: -> Illuminate \ Http \ Request kullanın; kalın Her ikisi de çakışacağından istek için ad alanını yeniden adlandırın
shalini

Orijinal cevap doğrudur. use RequestCepheyi kullanmaya çalıştığınız için içe aktarmanız gerekiyor . Sağladığınız ad alanı temeldeki sınıf içindir. Bunu içe aktarırsanız, bir hata alırsınız çünkü ip()statik olarak çağrılamaz, cephe bunun için.
jfadich

Sınıfa içe rahatsız yapacaksan, gerçek cepheyi değil, takma kullanmalısınız: use Illuminate\Support\Facades\Request. Değilse, sadece kullanın \Request::.
hackel

18

Laravel 5 için İstek nesnesini kullanabilirsiniz. Sadece ip()yöntemini çağırın , şöyle bir şey:

$request->ip();

16

Laravel 5 bölgesinde

public function index(Request $request) {
  $request->ip();
}

12

Dikkat edilmesi gereken iki şey var:

  1. A döndüren Illuminate\Http\Requestve ->ip()yöntemi çağıran bir yardımcı işlev alın :

    request()->ip();
  2. Sunucu yapılandırmanızı düşünün, bir proxy kullanabilir veya load-balancerözellikle bir AWS ELB yapılandırmasında.

Durumunuz buysa, " Güvenilen Proxy'leri Yapılandırma " yı izlemeniz veya hatta bir "Tüm Proxy'lere Güvenme" seçeneğini belirlemeniz gerekir.

Neden? Çünkü sunucunuz olmak load-balanceryerine proxy'nizi / IP'nizi alacak .

AWS denge yükleyicisindeyseniz, adresine gidin App\Http\Middleware\TrustProxiesve aşağıdaki $proxiesgibi bildirimde bulunun:

protected $proxies = '*';

Şimdi test edin ve kutlayın çünkü kendinizi kısma ara yazılımıyla ilgili sorunlardan kurtardınız. Ayrıca, request()->ip()"TrustProxies" ayarına da dayanır ve ayarlanmadan, yalnızca suçlunun IP'sini engellemek yerine tüm kullanıcılarınızın oturum açmasını engelleyebilirsiniz.

Ayrıca, kısma ara yazılımı belgelerde doğru bir şekilde açıklanmadığından, " yeni başlayanlar için laravel 5.2 öğreticisi, API Hız Sınırlaması " izlemenizi tavsiye ederim

Laravel 5.7'de test edildi


7

Laravel 5.4'te ip statik diyemeyiz. Bu, kullanıcının IP'sini almanın doğru bir yoludur:

 use Illuminate\Http\Request;

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

7

Bu işlevi çağırırsanız, müşterinin IP adresini kolayca alırsınız. Bunu zaten mevcut projemde kullandım:

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

IP olarak hala 127.0.0.1 alıyorsanız, "proxy" nizi eklemeniz gerekir, ancak üretime geçmeden önce onu değiştirmeniz gerektiğini unutmayın!

" Güvenilen Proxy'leri Yapılandırma " bölümünü okuyun .

Ve şunu ekleyin:

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

Şimdi request()->ip()size doğru IP'yi veriyor.




0

Sebastien Horin işlevini getIp ve request () -> ip () (genel istek üzerine) kullandım, çünkü localhost için getIp işlevi null döndürür:

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

GetIp işlevi:

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

Kullanıcının ip_address:

$_SERVER['REMOTE_ADDR']

ve sunucu adresi istiyorum:

$_SERVER['SERVER_ADDR']

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

1
Bunun neden tercih edilen çözüm olduğunu ve nasıl çalıştığını açıklarsanız daha fazla yardımcı olur. Sadece kod sağlamak değil, eğitmek istiyoruz. Olduğu gibi, sistem onu ​​düşük kaliteli olarak işaretliyor, bu yüzden iyileştirmeye çalışın.
The Tin Man

Öneriniz için teşekkür ederiz.
rashedcs
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.