Laravel 5 이상에서 클라이언트 IP 주소를 얻는 방법


136

Laravel에서 클라이언트의 IP 주소를 얻으려고합니다.

를 사용하여 PHP로 클라이언트의 IP를 쉽게 얻을 수 $_SERVER["REMOTE_ADDR"]있습니다. 핵심 PHP에서는 제대로 작동하지만 Laravel에서 동일한 것을 사용하면 방문자의 IP 대신 서버 IP를 반환합니다.

답변:


194

Laravel API 살펴보기 :

Request::ip();

내부적으로 Symfony Request ObjectgetClientIps메소드를 사용합니다 .

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
Request 객체를 사용하면 작동하지 않으며 홈스테드 서버의 주소를 반환합니다. 192.168.10.10 이것은 분명히 내 IP 주소가 아닙니다.
Vince Kronlein

귀하의 경우 @VinceKronlein이 답변을 확인하십시오 stackoverflow.com/a/41769505/3437790
Sebastien Horin

3
귀하의 경우에는 @VinceKronlein이 매우 정확했습니다. LOCAL 네트워크에서 Homestead에 액세스했기 때문에 192. IP가있었습니다. 인터넷을 통해 다른 사람의 홈 서버에 액세스하는 경우 IP가 ISP를 통해 나가고 공용 서버가 사용됩니다.
ied3vil

83

로드 밸런서에있는 경우 Laravel은 \Request::ip() 항상 밸런서의 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

이 사용자 정의 메소드는 실제 클라이언트 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;
                }
            }
        }
    }
}

이 외에도 Laravel의 스로틀 미들웨어를 사용하는 데 매우주의해야 합니다. Laravel도 사용 Request::ip()하므로 모든 방문자가 동일한 사용자로 식별되며 스로틀 한계에 매우 빨리 도달합니다. 나는이 라이브를 경험했고 이것은 큰 문제를 일으켰습니다.

이 문제를 해결하려면

Illuminate \ Http \ Request.php

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

이제 Request::ip()프로덕션에서 실제 IP를 반환해야하는을 사용할 수도 있습니다 .


1
if (filter_var ...)이 두 번째 foreach? 이 코드는 절대 실행되지 않습니다.
Mistre83

@ Mistre83 네, 맞습니다. 테스트 감독 인 것 같습니다. 업데이트합니다!
세바스티안 호린

6
이것은 실제로 laravel 5.4에서 작동합니다. github에서 PR을 만드는 것을 고려하십시오. 이것이 기본 행동이어야한다고 생각합니다
Crystal

1
Laravel 요청 객체의 IP () 메소드는 127.0.0.1 반환 유지 때 Laravel 5.3에서 치료를했다
w5m

3
신뢰할 수있는 프록시로이 문제를 해결 하시겠습니까? - laravel.com/docs/master/requests#configuring-trusted-proxies
user2722667

74

사용하십시오 request()->ip().

내가 이해 한 바에 따르면, Laravel 5부터 다음과 같은 전역 기능을 사용하는 것이 좋습니다.

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

그리고 정적 표기법 대신 함수를 사용할 때 IDE가 크리스마스 트리처럼 켜지지 않습니다.


3
당신은 request"글로벌"기능인 것이 맞습니다. 이것은 라 라벨이 제공하는 글로벌 헬퍼 기능 중 하나입니다. 그러나, 요청 외관은 정적되지 않습니다 (도 방법의 IP입니다) - request()->fooReqest::foo$request->foo모두 동일하다. 예를 들어이
Chris

1
충분히 공평합니다-둘 다 똑같이 맞습니다. 난 단지 당신이 "그것이 Request::ip오도 하지 않을 지도 모른다 "라고 생각한 부분을 생각했습니다
Chris

3
문제는 이러한 전역 함수를 쉽게 테스트 할 수 없으며 조롱 할 수 없다는 것입니다. 파사드가 될 수 있습니다. 전역 함수를 피하려고합니다. 전역 함수 소스를 파고 호출을 조롱하는 것을 의미하기 때문에 추가 작업이 필요하고 성가 시며 내 책임이되어서는 안됩니다.
hackel

1
하지만 request()->ip()특히이 아니다 "라고 - 올바른지, 주변의 텍스트는 정말 잘못된 것입니다 Request::ip.
크리스

1
@Chris 감사합니다, 당신은 절대적으로 맞습니다. 명확성을 위해 편집되었습니다!
Stan Smulders

27

네임 스페이스 추가

use Request;

그런 다음 함수를 호출하십시오.

Request::ip();

1
네임 스페이스를 사용하는 경우 :-> Use Illuminate \ Http \ Request; 굵은 글씨 둘 다 충돌하기 때문에 네임 스페이스 이름을 바꿉니다
shalini

원래 답변이 맞습니다. use RequestFacade를 사용하려고하므로 가져와야 합니다. 제공 한 네임 스페이스는 기본 클래스 용입니다. 가져 오기를하면 ip()정적으로 호출 될 수 없기 때문에 오류가 발생 합니다. 이것이 파사드의 목적입니다.
jfadich 2012

클래스 가져 오기를 귀찮게하려면 별명이 아닌 실제 파사드를 사용해야합니다 use Illuminate\Support\Facades\Request. 그렇지 않은 경우을 사용하십시오 \Request::.
hackel

18

Laravel 5의 경우 Request 객체를 사용할 수 있습니다. ip()다음과 같은 메소드를 호출하십시오 .

$request->ip();


12

처리해야 할 두 가지가 있습니다.

  1. a를 반환 Illuminate\Http\Request하고 ->ip()메서드를 호출 하는 도우미 함수를 가져옵니다 .

    request()->ip();
  2. 서버 구성을 생각해보십시오. 프록시를 사용하거나 load-balancer특히 AWS ELB 구성을 사용할 수 있습니다 .

이 경우 " 신뢰할 수있는 프록시 구성 "을 따르 거나 "모든 프록시 신뢰"옵션을 설정해야합니다.

왜? 서버가 프록시 / load-balancerIP를 대신 가져 오기 때문 입니다.

AWS 밸런스 로더를 사용중인 경우 다음과 같이 선언을 App\Http\Middleware\TrustProxies작성 $proxies하십시오.

protected $proxies = '*';

이제 스로틀 미들웨어에 문제가 발생하지 않았으므로 테스트하고 축하하십시오. 또한 request()->ip()"TrustProxies"를 설정하거나 설정하지 않아도 범인의 IP 만 차단하는 대신 모든 사용자의 로그인을 차단할 수 있습니다.

또한 스로틀 미들웨어에 대한 설명이 문서에 제대로 설명되어 있지 않으므로 " 초보자를위한 laravel 5.2 튜토리얼, API 속도 제한 "

Laravel 5.7에서 테스트


7

Laravel 5.4에서는 ip static을 호출 할 수 없습니다. 이것은 사용자의 IP를 얻는 올바른 방법입니다.

 use Illuminate\Http\Request;

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

7

이 함수를 호출하면 클라이언트의 IP 주소를 쉽게 얻을 수 있습니다. 기존 프로젝트에서 이미 이것을 사용했습니다.

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을 IP로 받고 있다면 "프록시"를 추가해야하지만 프로덕션으로 가기 전에 변경해야합니다.

" 신뢰할 수있는 프록시 구성 "을 읽으십시오 .

그리고 이것을 추가하십시오 :

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

이제 request()->ip()올바른 IP를 제공합니다.



0

CDN +로드 밸런서와 같이 여러 계층 프록시가있는 경우
Laravel Request :: ip () 함수를 사용하면 클라이언트 IP가 아닌 가장 오른쪽 프록시 IP를 얻습니다.
다음 해결책을 시도해 볼 수 있습니다.

app / Http / Middleware / TrustProxies.php

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

참조 : https://github.com/fideloper/TrustedProxy/issues/107#issuecomment-373065215


0

로컬 호스트에 getIp 함수가 null을 반환하기 때문에 Sebastien Horin 함수 getIp 및 request ()-> ip () (전역 요청)를 사용했습니다.

$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_address:

$_SERVER['REMOTE_ADDR']

서버 주소를 원합니다.

$_SERVER['SERVER_ADDR']

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

1
왜 이것이 바람직한 솔루션인지 설명하고 작동 방식을 설명하면 도움이됩니다. 우리는 단지 코드를 제공하는 것이 아니라 교육하기를 원합니다. 시스템이 품질이 낮은 것으로 표시되어 있으므로 개선해보십시오.
Tin Man

제안 해 주셔서 감사합니다.
rashedcs 2009
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.