如何在Laravel 5+中获取客户端IP地址?

问题描述 投票:101回答:12

我想在Laravel中获取客户端的IP地址。众所周知,使用$_SERVER["REMOTE_ADDR"]在PHP中获取客户端的IP要容易得多。

它在核心PHP中运行良好,但是当我在Laravel中使用相同的东西时,它会提供服务器IP而不是访问者IP。

php laravel laravel-5 laravel-5.1 laravel-5.7
12个回答
139
投票

看着Laravel API

Request::ip();

在内部,它使用getClientIps中的Symfony Request Object方法:

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

2
投票

如果您调用此功能,则可以轻松获取客户端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;
    }

1
投票

有两件事需要照顾

1)得到辅助函数,返回一个Illuminate\Http\Request并调用->ip()方法。

request()->ip();

2)想想你的服务器配置,它可能会使用proxyload balancer(特别是在AWS ELB配置中)

如果这是你的情况,你需要Configuring Trusted Proxies或甚至可能设置一个Trusting All Proxiesoption。

为什么?

因为作为您的服务器将获得代理/平衡加载器IP。

怎么样?

如果你不是AWS balance-loader

App\Http\Middleware\TrustProxies

并使$proxies声明看起来像这样:

protected $proxies = '*';

现在测试并庆祝,因为你刚刚从throttle middleware遇到麻烦。它还依赖于request()->ip()并且没有设置TrustProxies,你可以阻止所有用户登录而不是仅阻止罪魁祸首的IP。

因为在文档中没有正确解释throttle middleware,我建议观看this video

在Laravel 5.7中测试过


-3
投票

当我们想要用户的ip_address时:

$_SERVER['REMOTE_ADDR']

并希望服务器地址:

$_SERVER['SERVER_ADDR']

55
投票

使用request()->ip()

从Laravel 5开始(根据我的理解)建议/良好实践使用全局函数,如:

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

你明白了这一点:-)如果有的话,当使用这些函数(而不是静态的notarion)时,我的IDE就不会像圣诞树一样;-)


51
投票

If you are under a load balancer

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的油门中间件要非常小心:它也使用Laravel的Request::ip(),所以你的所有访客都将被识别为同一个用户,你很快就会达到油门限制。在现场体验......这让我遇到了大问题......

解决这个问题:

照亮\ HTTP \ Request.php

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

您现在也可以使用Request::ip(),它应该返回生产中的真实IP


22
投票

添加命名空间

use Request;

然后调用该函数

Request::ip();

12
投票

对于Laravel 5,您可以使用Request对象。只需调用其ip()方法即可。就像是:

$request->ip();


9
投票

在Laravel 5

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

3
投票

如果您仍然获得127.0.0.1作为IP,则需要添加“代理”。

但要注意,你必须在生产前改变它!

阅读本部分:https://laravel.com/docs/5.7/requests#configuring-trusted-proxies

现在只需添加:

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

现在请求() - > ip()为您提供正确的IP


2
投票

在版本laravel 5.4中我们无法调用ip static这是获取ip用户的正确方法

 use Illuminate\Http\Request;

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

2
投票

如果您想要客户端IP并且您的服务器位于aws elb之后,请使用以下代码。测试laravel 5.3

$elbSubnet = '172.31.0.0/16';
Request::setTrustedProxies([$elbSubnet]);
$clientIp = $request->ip();
© www.soinside.com 2019 - 2024. All rights reserved.