laravel获取客户端 IP 地址两种方式

1 laravel自带方法获取客户端ip

dd(request()->ip());
var_dump(request()->getClientIp());

laravel获取客户端 IP 地址两种方式_第1张图片
但是,这是在没有代理的情况下,有时候我们的业务使用了反向代理、负载均衡、cdn加速等等,我们就要设置信任的代理IP。

修改 app\Http\Middleware\TrustProxies.php 中的 $proxies

protected $proxies = [
    '192.168.1.1/24',//你信任的代理IP,支持IP段。
];

如果你不清楚代理服务器IP,或者IP会一直变动。可以设置信任所有代理。(这样是极其不安全的,用户可以伪造X-Forwarded-For来伪造IP)

网段192.168.1.0/24是什么意思?

192.168.1.0/24表示网段是192.168.1.0,子网掩码是24位,子网掩码为:255.255.255.0,
用二进制表示为:11111111 11111111 11111111 00000000 ,
这里为什么是24呢,就是因为子网掩码里面的前面连续的“1”的个数为24个,一定要连续的才行。

192.168.1.0/28表示的意思是网段是192.168.1.0,子网掩码为:255.255.255.240,
用二进制表示为:11111111 11111111 11111111 11110000。

这时候你也许就疑惑了,就是24和28两个字不一样,为什么网段是一样的呢?

24位说明网络位是24位,那么主机位就是32-24=8位了,则子网的IP个数是254个,即是从00000001到11111110.
28位说明网络位是28位,那么主机位4位,则子网的IP个数是14个,即是从00000001到00001110.

protected $proxies = '**';

2 自定义函数获取客户端IP



namespace App\Http\Controllers;

class TestController extends Controller
{
     
    public function ip()
    {
     
        dd($this->getClientIp());
    }
    /**
     * 获取用户真实 ip
     * @return array|false|mixed|string
     */
    private function getClientIp()
    {
     
        if (getenv('HTTP_CLIENT_IP')) {
     
            $ip = getenv('HTTP_CLIENT_IP');
        }
        if (getenv('HTTP_X_REAL_IP')) {
     
            $ip = getenv('HTTP_X_REAL_IP');
        } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
     
            $ip = getenv('HTTP_X_FORWARDED_FOR');
            $ips = explode(',', $ip);
            $ip = $ips[0];
        } elseif (getenv('REMOTE_ADDR')) {
     
            $ip = getenv('REMOTE_ADDR');
        } else {
     
            $ip = '0.0.0.0';
        }

        return $ip;
    }
}

laravel获取客户端 IP 地址两种方式_第2张图片

getenv —获取环境变量的值

(PHP 4,PHP 5,PHP 7,PHP 8)
getenv —获取环境变量的值

var_dump(getenv('PATH'));

string(106) "/usr/local/node/bin:/usr/local/jdk-12.0.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

HTTP_CLIENT_IP

HTTP_CLIENT_IP 是代理服务器发送的HTTP头。如果是“超级匿名代理”,则返回none值。同样,REMOTE_ADDR也会被替换为这个代理服务器的IP。

$_SERVER['HTTP_CLIENT_IP']; //代理端的(有可能存在,可伪造)

HTTP_X_REAL_IP

nginx 代理模式下,获取客户端真实IP

$_SERVER['HTTP_X_REAL_IP']; // 得到的都是客户端的地址

在nginx中设置:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

后端程序可以从Server变量HTTP_X_REAL_IP和HTTP_X_FORWARDED_FOR中获取用户的ip地址。

HTTP_X_REAL_IP的值是nginx得到的用户REMOTE_ADDR。

HTTP_X_FORWARDED_FOR

$_SERVER['HTTP_X_FORWARDED_FOR']; //用户是在哪个IP使用的代理(有可能存在,也可以伪造)
一、没有使用代理服务器的情况:

REMOTE_ADDR = 您的 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示

二、使用透明代理服务器的情况:Transparent Proxies

REMOTE_ADDR = 最后一个代理服务器 IP 
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 您的真实 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。

三、使用普通匿名代理服务器的情况:Anonymous Proxies

REMOTE_ADDR = 最后一个代理服务器 IP 
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

隐藏了您的真实IP,但是向访问对象透露了您是使用代理服务器访问他们的。

四、使用欺骗性代理服务器的情况:Distorting Proxies

REMOTE_ADDR = 代理服务器 IP 
HTTP_VIA = 代理服务器 IP 
HTTP_X_FORWARDED_FOR = 随机的 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。

五、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)

REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示 ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

REMOTE_ADDR

如果不想获取代理ip需要对NGINX进行设置。

$_SERVER['REMOTE_ADDR']; //访问端(有可能是用户,有可能是代理的)IP

表示发出请求的远程主机的 IP 地址,remote_addr代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等)就会把remote_addr设为你的机器IP,如果你用了某个代理,那么你的浏览器会先访问这个代理,然后再由这个代理转发到网站,这样web服务器就会把remote_addr设为这台代理机器的IP。

x_forwarded_for

简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项,正如上面所述,当你使用了代理时,web服务器就不知道你的真实IP了,为了避免这个情况,代理服务器通常会增加一个叫做x_forwarded_for的头信息,把连接它的客户端IP(即你的上网机器IP)加到这个头信息里,这样就能保证网站的web服务器能获取到真实IP。

格式一般为:

X-Forwarded-For: 1.1.1.1, 2.2.2.2, 3.3.3.3

代表 请求由1.1.1.1发出,经过三层代理,第一层是2.2.2.2,第二层是3.3.3.3,而本次请求的来源IP4.4.4.4是第三层代理。

laravel获取客户端 IP 地址两种方式_第3张图片

场景1

是很简单的场景,Nginx Proxy直接把请求往后转发,没有做任何处理

Nginx Proxy
192.168.107.107 nginx.conf
location /test {
    proxy_pass http://192.168.107.112:8080;
}
192.168.107.112 nginx.conf
location /test {
    proxy_pass http://192.168.107.114:8080;
}
Nginx Proxy就是简单的把请求往后转发。
Nginx Backend
192.168.107.114 nginx.conf
location /test {
    default_type text/html;
    charset gbk;
    echo "$remote_addr || $http_x_forwarded_for";
}

Nginx Backend输出客户端IP( r e m o t e a d d r ) 和 X − F o r w a r d e d − F o r 请 求 头 ( remote_addr)和X-Forwarded-For请求头( remoteaddrXForwardedForhttp_x_forwarded_for),当访问服务时输出结果如下所示:

192.168.107.112 ||

分析
1.$remote_addr代表客户端IP,当前配置的输出结果为最后一个代理服务器的IP,并不是真实客户端IP;

2.在没有特殊配置情况下,X-Forwarded-For请求头不会自动添加到请求头中,即Nginx Backend的$http_x_forwarded_for输出为空。

3 PHP判断ip范围

判断192.168.1.127是否在 (192.168.1.1–192.168.1.255)的范围

定义变量 注释
$ip_start = get_iplong(‘192.168.1.1’); 起始ip
$ip_end = get_iplong(‘192.168.1.255’); 结束ip
$ip = get_iplong(‘192.168.1.127’); 判断的ip
//可以这样简单判断  
if($ip>=$ip_start && $ip <=$ip_end){
       
    echo 'IP在此范围内';  
}else{
       
    echo 'IP不在此范围';  
}  
/*将ip地址转换成int型*/  
function get_iplong($ip){
       
    /*decbin() 函数把十进制数转换为二进制数,bindec() 函数把二进制转换为十进制。
      ip2long();的意思是将IP地址转换成整型 ,  
      之所以要decbin和bindec一下是为了防止IP数值过大int型存储不了出现负数。 */ 
    return bindec(decbin(ip2long($ip)));  
}

4 获取客户端ip方法



namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TestContainer extends Controller
{
     
	# 获取客户端ip
    public function containers()
    {
     
    	if (getenv("HTTP_CLIENT_IP")) {
     
			$ip = getenv("HTTP_CLIENT_IP");
		}
		else if (getenv("HTTP_X_FORWARDED_FOR")) {
     
			$ip = getenv("HTTP_X_FORWARDED_FOR");
		}
		else if (getenv("HTTP_X_FORWARDED")) {
     
			$ip = getenv("HTTP_X_FORWARDED");
		}
		else if (getenv("HTTP_FORWARDED_FOR")) {
     
			$ip = getenv("HTTP_FORWARDED_FOR");
		}
		else if (getenv("HTTP_FORWARDED")) {
     
			$ip = getenv("HTTP_FORWARDED");
		}
		else {
     
			$ip = $_SERVER["REMOTE_ADDR"];
		}
	 
		return $ip;
    }
}

你可能感兴趣的:(laravel)