简体   繁体   English

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

[英]How to get client IP address in Laravel 5+

I am trying to get the client's IP address in Laravel.我正在尝试在 Laravel 中获取客户端的 IP 地址。

It is easy to get a client's IP in PHP by using $_SERVER["REMOTE_ADDR"] .使用$_SERVER["REMOTE_ADDR"]很容易在 PHP 中获取客户端的 IP。 It is working fine in core PHP, but when I use the same thing in Laravel, it returns the server IP instead of the visitor's IP.它在核心 PHP 中运行良好,但是当我在 Laravel 中使用相同的东西时,它返回服务器 IP 而不是访问者的 IP。

Looking at the Laravel API<\/a> :查看Laravel API<\/a> :

Request::ip();

If you are under a load balancer, Laravel's \\Request::ip() always returns the balancer's 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

This custom method returns the real client 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;
                }
            }
        }
    }
    return request()->ip(); // it will return server ip when no client ip found
}

In addition to this I suggest you to be very careful using Laravel's throttle middleware: It uses Laravel's Request::ip() as well, so all your visitors will be identified as the same user and you will hit the throttle limit very quickly.除此之外,我建议您在使用 Laravel 的油门中间件时要非常小心:它也使用 Laravel 的Request::ip() ,因此您的所有访问者都将被识别为同一用户,您将很快达到油门限制。 I experienced this live and this caused big issues.我经历了这种生活,这引起了大问题。

To fix this:要解决这个问题:

Illuminate\\Http\\Request.php照亮\\Http\\Request.php

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

You can now also use Request::ip() , which should return the real IP in production.您现在还可以使用Request::ip() ,它应该返回生产中的真实 IP。

Use request()->ip()<\/code> .使用request()->ip()<\/code> 。

From what I understand, since Laravel 5 it's advised\/good practice to use the global functions like:据我了解,从 Laravel 5 开始,建议\/良好的做法是使用以下全局函数:

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

Add namespace添加命名空间

use Request;

For Laravel 5 you can use the Request object.对于 Laravel 5,您可以使用 Request 对象。 Just call its ip() method, something like:只需调用它的ip()方法,例如:

$request->ip();

There are two things to take care of:有两件事需要注意:

  1. Get a helper function that returns a Illuminate\\Http\\Request and call the ->ip() method:获取一个返回Illuminate\\Http\\Request的辅助函数并调用->ip()方法:

     request()->ip();
  2. Think of your server configuration, it may use a proxy or load-balancer , especially in an AWS ELB configuration.想想您的服务器配置,它可能使用代理或load-balancer ,尤其是在 AWS ELB 配置中。

If this is your case you need to follow " Configuring Trusted Proxies " or maybe even set a "Trusting All Proxies" option.如果这是您的情况,您需要遵循“ 配置受信任的代理”,或者甚至设置“信任所有代理”选项。

Why?为什么? Because being your server will be getting your proxy/ load-balancer IP instead.因为作为您的服务器将获得您的代理/ load-balancer IP。

If you are on the AWS balance-loader, go to App\\Http\\Middleware\\TrustProxies and make $proxies declaration look like this:如果您在 AWS balance-loader 上,请转到App\\Http\\Middleware\\TrustProxies并使$proxies声明如下所示:

protected $proxies = '*';

Now test it and celebrate because you just saved yourself from having trouble with throttle middleware.现在测试它并庆祝一下,因为您刚刚使自己免于遇到油门中间件的麻烦。 It also relies on request()->ip() and without setting "TrustProxies" up, you could have all your users blocked from logging in instead of blocking only the culprit's IP.它还依赖于request()->ip()并且在不设置“TrustProxies”的情况下,您可以阻止所有用户登录,而不是仅阻止罪魁祸首的 IP。

And because throttle middleware is not explained properly in the documentation, I recommend watching " laravel 5.2 tutorial for beginner, API Rate Limiting "并且由于文档中没有正确解释油门中间件,我建议观看“ laravel 5.2 初学者教程,API 速率限制

Tested in Laravel 5.7在 Laravel 5.7 中测试

In Laravel 5在 Laravel 5

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

I tested in Laravel 8.x and you can use:我在 Laravel 8.x 中测试过,你可以使用:

$request->ip()

If you call this function then you easily get the client's IP address.如果你调用这个函数,那么你很容易得到客户端的 IP 地址。 I have already used this in my existing project:我已经在我现有的项目中使用了它:

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

In Laravel 5.4 we can't call ip static.在 Laravel 5.4 中,我们不能调用 ip static。 This a correct way to get the IP of the user:这是获取用户IP的正确方法:

 use Illuminate\Http\Request;

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

If you are still getting 127.0.0.1 as the IP, you need to add your "proxy", but be aware that you have to change it before going into production!如果您仍然获得 127.0.0.1 作为 IP,您需要添加您的“代理”,但请注意在投入生产之前您必须更改它!

Read " Configuring Trusted Proxies ".阅读“ 配置可信代理”。

And add this:并添加:

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

Now request()->ip() gives you the correct IP.现在request()->ip()为您提供正确的 IP。

If you want client IP and your server is behind aws elb, then user the following code.如果您想要客户端 IP 并且您的服务器位于 aws elb 之后,请使用以下代码。 Tested for laravel 5.3测试 laravel 5.3

$elbSubnet = '172.31.0.0/16';
Request::setTrustedProxies([$elbSubnet]);
$clientIp = $request->ip();

You can get a few way ip address utilizing Request ip, Request getClientIp and solicitation partner work.您可以使用 Request ip、Request getClientIp 和请求合作伙伴的工作获得几种方式的 ip 地址。 In this model, I will tell you the best way to get current client ip address in laravel 5.8.在这个模型中,我将告诉你在 laravel 5.8 中获取当前客户端 IP 地址的最佳方法。

$clientIP = request()->ip();

dd($clientIP);

You can follow this from here你可以从这里关注这个

Solution 1: You can use this type of function for getting client IP解决方案 1:您可以使用此类函数获取客户端 IP

public function getClientIPaddress(Request $request) {
    $clientIp = $request->ip();
    return $clientIp;
}

Solution 2: if the solution1 is not providing accurate IP then you can use this function for getting visitor real IP.解决方案2:如果解决方案1没有提供准确的IP ,那么您可以使用此功能获取访问者真实IP。

 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: When you have used load-balancer / proxy-server in your live server then you need to used solution 2 for getting real visitor ip.注意:当您在实时服务器中使用负载平衡器/代理服务器时,您需要使用解决方案 2来获取真正的访问者 IP。

If you have multiple layer proxies just like CDN + Load Balancer.如果您有多层代理,例如 CDN + 负载均衡器。
Using Laravel Request::ip() function will get right-most proxy IP but not client IP.使用 Laravel Request::ip() 函数将获得最右边的代理 IP,而不是客户端 IP。
You may try following solution.您可以尝试以下解决方案。

app\/Http\/Middleware\/TrustProxies.php app\/Http\/Middleware\/TrustProxies.php

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

I used the Sebastien Horin function getIp and request()->ip() (at global request), because to localhost the getIp function return null:我使用了 Sebastien Horin 函数 getIp 和 request()->ip()(在全局请求中),因为对于 localhost,getIp 函数返回 null:

$this->getIp() ?? request()->ip();<\/code>

The getIp function: 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;
            }
        }
    }
}

If you worry about getting the IP address but do not need or want to use any Laravel functionality, you can use just php:如果您担心获取 IP 地址但不需要或不想使用任何 Laravel 功能,您可以只使用 php:

PHP < 5.3.0 PHP < 5.3.0
$localIP = getHostByName(php_uname('n')); $localIP = getHostByName(php_uname('n'));

PHP >= 5.3.0 PHP >= 5.3.0
$localIP = getHostByName(getHostName()); $localIP = getHostByName(getHostName());

as answered in this thread: PHP how to get local IP of system<\/a>正如在这个线程中回答的那样: PHP 如何获取系统的本地 IP<\/a>

"

This solution I used in my project.我在我的项目中使用的这个解决方案。 I found other solutions here either incomplete or too complex to understand.我发现这里的其他解决方案要么不完整,要么太复杂而无法理解。

if (! function_exists('get_visitor_IP'))
{
    /**
     * Get the real IP address from visitors proxy. e.g. Cloudflare
     *
     * @return string IP
     */
    function get_visitor_IP()
    {
        // Get real visitor IP behind CloudFlare network
        if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
            $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
            $_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
        }

        // Sometimes the `HTTP_CLIENT_IP` can be used by proxy servers
        $ip = @$_SERVER['HTTP_CLIENT_IP'];
        if (filter_var($ip, FILTER_VALIDATE_IP)) {
           return $ip;
        }

        // Sometimes the `HTTP_X_FORWARDED_FOR` can contain more than IPs 
        $forward_ips = @$_SERVER['HTTP_X_FORWARDED_FOR'];
        if ($forward_ips) {
            $all_ips = explode(',', $forward_ips);

            foreach ($all_ips as $ip) {
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)){
                    return $ip;
                }
            }
        }

        return $_SERVER['REMOTE_ADDR'];
    }
}

为我工作

$requestIp  = \Request::ip();

When we want the user's ip_address :当我们想要用户的ip_address时:

$_SERVER['REMOTE_ADDR']

and want to server address:并希望服务器地址:

$_SERVER['SERVER_ADDR']
  $ip = $_SERVER['REMOTE_ADDR'];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM