답변:
Laravel API 살펴보기 :
Request::ip();
내부적으로 Symfony Request Object 의 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);
}
로드 밸런서에있는 경우 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를 반환해야하는을 사용할 수도 있습니다 .
사용하십시오 request()->ip()
.
내가 이해 한 바에 따르면, Laravel 5부터 다음과 같은 전역 기능을 사용하는 것이 좋습니다.
response()->json($v);
view('path.to.blade');
redirect();
route();
cookie();
그리고 정적 표기법 대신 함수를 사용할 때 IDE가 크리스마스 트리처럼 켜지지 않습니다.
Request::ip
오도 하지 않을 지도 모른다 "라고 생각한 부분을 생각했습니다
request()->ip()
특히이 아니다 "라고 - 올바른지, 주변의 텍스트는 정말 잘못된 것입니다 Request::ip
.
네임 스페이스 추가
use Request;
그런 다음 함수를 호출하십시오.
Request::ip();
use Request
Facade를 사용하려고하므로 가져와야 합니다. 제공 한 네임 스페이스는 기본 클래스 용입니다. 가져 오기를하면 ip()
정적으로 호출 될 수 없기 때문에 오류가 발생 합니다. 이것이 파사드의 목적입니다.
use Illuminate\Support\Facades\Request
. 그렇지 않은 경우을 사용하십시오 \Request::
.
처리해야 할 두 가지가 있습니다.
a를 반환 Illuminate\Http\Request
하고 ->ip()
메서드를 호출 하는 도우미 함수를 가져옵니다 .
request()->ip();
서버 구성을 생각해보십시오. 프록시를 사용하거나 load-balancer
특히 AWS ELB 구성을 사용할 수 있습니다 .
이 경우 " 신뢰할 수있는 프록시 구성 "을 따르 거나 "모든 프록시 신뢰"옵션을 설정해야합니다.
왜? 서버가 프록시 / load-balancer
IP를 대신 가져 오기 때문 입니다.
AWS 밸런스 로더를 사용중인 경우 다음과 같이 선언을 App\Http\Middleware\TrustProxies
작성 $proxies
하십시오.
protected $proxies = '*';
이제 스로틀 미들웨어에 문제가 발생하지 않았으므로 테스트하고 축하하십시오. 또한 request()->ip()
"TrustProxies"를 설정하거나 설정하지 않아도 범인의 IP 만 차단하는 대신 모든 사용자의 로그인을 차단할 수 있습니다.
또한 스로틀 미들웨어에 대한 설명이 문서에 제대로 설명되어 있지 않으므로 " 초보자를위한 laravel 5.2 튜토리얼, API 속도 제한 "
Laravel 5.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;
}
여전히 127.0.0.1을 IP로 받고 있다면 "프록시"를 추가해야하지만 프로덕션으로 가기 전에 변경해야합니다.
" 신뢰할 수있는 프록시 구성 "을 읽으십시오 .
그리고 이것을 추가하십시오 :
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array
*/
protected $proxies = '*';
이제 request()->ip()
올바른 IP를 제공합니다.
클라이언트 IP를 원하고 서버가 aws elb 뒤에 있으면 다음 코드를 사용하십시오. 라 라벨 5.3 테스트
$elbSubnet = '172.31.0.0/16';
Request::setTrustedProxies([$elbSubnet]);
$clientIp = $request->ip();
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
로컬 호스트에 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;
}
}
}
}
}
우리가 사용자를 원할 때 ip_address
:
$_SERVER['REMOTE_ADDR']
서버 주소를 원합니다.
$_SERVER['SERVER_ADDR']
$ip = $_SERVER['REMOTE_ADDR'];