Próbuję uzyskać adres IP klienta w Laravel.
Uzyskanie adresu IP klienta w PHP jest łatwe przy użyciu $_SERVER["REMOTE_ADDR"]
. Działa dobrze w rdzeniu PHP, ale kiedy używam tego samego w Laravel, zwraca IP serwera zamiast IP odwiedzającego.
Próbuję uzyskać adres IP klienta w Laravel.
Uzyskanie adresu IP klienta w PHP jest łatwe przy użyciu $_SERVER["REMOTE_ADDR"]
. Działa dobrze w rdzeniu PHP, ale kiedy używam tego samego w Laravel, zwraca IP serwera zamiast IP odwiedzającego.
Odpowiedzi:
Patrząc na Laravel API :
Request::ip();
Wewnętrznie używa getClientIps
metody z obiektu żądania Symfony :
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);
}
Jeśli korzystasz z modułu równoważenia obciążenia, Laravel \Request::ip()
zawsze zwraca adres IP modułu równoważenia:
echo $request->ip();
// server ip
echo \Request::ip();
// server ip
echo \request()->ip();
// server ip
echo $this->getIp(); //see the method below
// clent ip
Ta niestandardowa metoda zwraca rzeczywisty adres IP klienta:
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;
}
}
}
}
}
Oprócz tego sugeruję, abyś był bardzo ostrożny podczas korzystania z oprogramowania pośredniego przepustnicy Laravel : używa Request::ip()
również oprogramowania Laravel , więc wszyscy odwiedzający zostaną zidentyfikowani jako ten sam użytkownik i bardzo szybko osiągniesz limit przepustnicy. Doświadczyłem tego na żywo i spowodowało to duże problemy.
Aby to naprawić:
Illuminate \ Http \ Request.php
public function ip()
{
//return $this->getClientIp(); //original method
return $this->getIp(); // the above method
}
Możesz teraz również użyć Request::ip()
, co powinno zwrócić prawdziwy adres IP w produkcji.
Użyj request()->ip()
.
Z tego, co rozumiem, od Laravel 5 zaleca się / dobrą praktyką korzystanie z funkcji globalnych, takich jak:
response()->json($v);
view('path.to.blade');
redirect();
route();
cookie();
I jeśli już, kiedy używam funkcji zamiast statycznej notacji, moje IDE nie świeci jak choinka.
request
jest to funkcja „globalna” - jest to jedna z globalnych funkcji pomocniczych udostępnianych przez laravel. Jednak fasada Zapytanie nie jest statyczna (ani nie jest metoda IP) - request()->foo
i Reqest::foo
i $request->foo
są identyczne. Spójrz na tę istotę na przykład: gist.github.com/cjke/026e3036c6a10c672dc5
Request::ip
może być mylące
request()->ip()
jest poprawna, otaczający tekst jest bardzo mylące - zwłaszcza powiedzieć „to nie jest Request::ip
.
Dodaj przestrzeń nazw
use Request;
Następnie wywołaj funkcję
Request::ip();
use Request
ponieważ próbujesz użyć elewacji. Podana przestrzeń nazw jest przeznaczona dla klasy bazowej. Jeśli zaimportujesz, otrzymasz błąd, ponieważ ip()
nie można go nazwać statycznie, do tego służy fasada.
use Illuminate\Support\Facades\Request
. Jeśli nie, po prostu użyj \Request::
.
W przypadku Laravel 5 możesz użyć obiektu Request. Po prostu wywołaj jego ip()
metodę, na przykład:
$request->ip();
W Laravel 5
public function index(Request $request) {
$request->ip();
}
Należy zadbać o dwie rzeczy:
Pobierz funkcję pomocniczą, która zwraca a Illuminate\Http\Request
i wywołaj ->ip()
metodę:
request()->ip();
Pomyśl o konfiguracji serwera, może on korzystać z serwera proxy lub load-balancer
, zwłaszcza w konfiguracji AWS ELB.
Jeśli tak jest w Twoim przypadku, musisz postępować zgodnie z sekcją „ Konfigurowanie zaufanych serwerów proxy ” lub nawet ustawić opcję „Zaufanie wszystkim proxy”.
Czemu? Ponieważ bycie twoim serwerem spowoduje load-balancer
zamiast tego twój proxy / IP.
Jeśli jesteś na wyważarce AWS, przejdź do App\Http\Middleware\TrustProxies
i spraw, aby $proxies
deklaracja wyglądała następująco:
protected $proxies = '*';
Teraz przetestuj to i świętuj, ponieważ właśnie uratowałeś się przed problemami z oprogramowaniem pośredniczącym przepustnicy. Opiera się również na request()->ip()
i bez ustawiania "TrustProxies", możesz zablokować wszystkim swoim użytkownikom logowanie zamiast blokowania tylko adresu IP winowajcy.
A ponieważ oprogramowanie pośredniczące przepustnicy nie jest prawidłowo wyjaśnione w dokumentacji, polecam obejrzenie „ samouczka laravel 5.2 dla początkujących, ograniczanie szybkości interfejsu API ”
Przetestowano w Laravel 5.7
W Laravel 5.4 nie możemy wywołać ip static. Oto poprawny sposób na uzyskanie adresu IP użytkownika:
use Illuminate\Http\Request;
public function contactUS(Request $request)
{
echo $request->ip();
return view('page.contactUS');
}
Jeśli wywołasz tę funkcję, łatwo uzyskasz adres IP klienta. Użyłem już tego w moim istniejącym projekcie:
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;
}
Jeśli nadal otrzymujesz adres IP 127.0.0.1, musisz dodać swoje „proxy”, ale pamiętaj, że musisz je zmienić przed rozpoczęciem produkcji!
Przeczytaj „ Konfigurowanie zaufanych serwerów proxy ”.
I dodaj to:
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array
*/
protected $proxies = '*';
Teraz request()->ip()
podaje poprawny adres IP.
Jeśli chcesz IP klienta, a twój serwer jest za aws elb, użyj następującego kodu. Przetestowano na laravel 5.3
$elbSubnet = '172.31.0.0/16';
Request::setTrustedProxies([$elbSubnet]);
$clientIp = $request->ip();
Rozwiązanie 1: Funkcji tego typu można użyć do uzyskania adresu IP klienta
public function getClientIPaddress(Request $request) {
$clientIp = $request->ip();
return $clientIp;
}
Rozwiązanie 2: jeśli rozwiązanie 1 nie zapewnia dokładnego adresu IP , możesz użyć tej funkcji do uzyskania prawdziwego adresu IP gościa.
public function getClientIPaddress(Request $request) {
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
$_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}
$client = @$_SERVER['HTTP_CLIENT_IP'];
$forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
$remote = $_SERVER['REMOTE_ADDR'];
if(filter_var($client, FILTER_VALIDATE_IP)){
$clientIp = $client;
}
elseif(filter_var($forward, FILTER_VALIDATE_IP)){
$clientIp = $forward;
}
else{
$clientIp = $remote;
}
return $clientIp;
}
NB: Jeśli użyłeś modułu równoważenia obciążenia / serwera proxy na swoim serwerze rzeczywistym, musisz użyć rozwiązania 2, aby uzyskać prawdziwy adres IP dla gości.
Możesz uzyskać adres IP na kilka sposobów, wykorzystując żądanie IP, żądanie getClientIp i współpracę z partnerem w zakresie pozyskiwania. W tym modelu powiem Ci najlepszy sposób na uzyskanie aktualnego adresu IP klienta w laravel 5.8.
$clientIP = request()->ip();
dd($clientIP);
Możesz śledzić to stąd
Jeśli masz wiele serwerów proxy, tak jak CDN + Load Balancer.
Użycie funkcji Laravel Request :: ip () spowoduje uzyskanie prawego adresu IP proxy, ale nie adresu IP klienta.
Możesz spróbować następującego rozwiązania.
app / Http / Middleware / TrustProxies.php
protected $proxies = ['0.0.0.0/0'];
Źródła: https://github.com/fideloper/TrustedProxy/issues/107#issuecomment-373065215
Użyłem funkcji Sebastiena Horina getIp i request () -> ip () (na żądanie globalne), ponieważ do localhost funkcja getIp zwraca null:
$this->getIp() ?? request()->ip();
Funkcja 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;
}
}
}
}
}
Jeśli martwisz się o uzyskanie adresu IP, ale nie potrzebujesz lub nie chcesz korzystać z żadnej funkcjonalności Laravel, możesz użyć tylko php:
PHP <5.3.0
$ localIP = getHostByName (php_uname ('n'));
PHP> = 5.3.0
$ localIP = getHostByName (getHostName ());
jak odpowiedział w tym wątku: PHP jak uzyskać lokalny adres IP systemu
Kiedy chcemy, aby użytkownik ip_address
:
$_SERVER['REMOTE_ADDR']
i chcę adres serwera:
$_SERVER['SERVER_ADDR']
$ip = $_SERVER['REMOTE_ADDR'];