PHP实战开发23-PHP结合Nginx获取用户真实IP地址


一、前言

本文已收录于PHP全栈系列专栏:PHP快速入门与实战

在Web应用程序中,IP地址是常见的数据项。例如,它可以用于用户认证、访问控制、日志记录和其他安全功能。然而,在某些情况下,获取客户端的真实IP地址可能会变得非常困难。
在这里插入图片描述

由于HTTP协议的本质,当您从Web服务器接收请求时,它只包含HTTP头中的客户端的最后一个代理服务器的IP地址。这称为X-Forwarded-For头。

因此,如果您希望了解客户端的真实IP地址,则需要深入探究HTTP请求如何跨多个代理服务器传递。

本文将向您展示如何使用PHP和Nginx来获取客户端的真实IP地址。

二、关于用户IP的背景知识

在深入探讨代码之前,我们需要先了解一些基础知识。如什么是HTTP,HTTP请求包含了哪些信息。请求到服务器这个过程是怎么一回事等。

2.1 HTTP请求

在这里插入图片描述

HTTP请求由请求行、请求头和请求体组成。

请求行指定请求方法(GET、POST等)、URI和HTTP协议的版本号。

请求头包含HTTP版本、Host头、User-Agent头、Cookie头和其他自定义头部。

请求体包含客户端提交的数据,通常是表单数据或JSON数据。

2.2 HTTP代理服务器

HTTP代理服务器是介于客户端和Web服务器之间的一种服务器。代理服务器可以用于缓存、负载均衡、安全性和其他目的。当客户端向代理服务器发出HTTP请求时,代理服务器将该请求转发到下一个目标服务器。

在这里插入图片描述

2.3 X-Forwarded-For头部

X-Forwarded-For头是一种HTTP头部,用于指示客户端的真实IP地址。当Web服务器从代理服务器接收请求时,它会检查X-Forwarded-For头,并提取最后一个IP地址。如果此头不存在,则Web服务器将使用代理服务器的IP地址。

如果请求通过多个代理服务器传递,则每个代理服务器都可以在X-Forwarded-For头中添加一个IP地址。在这种情况下,最后一个IP地址是客户端的真实IP地址。

三、代码实现

3.1 Nginx配置

PHP代码正常工作,我们需要在Nginx服务器上启用X-Forwarded-For头部。这是通过将以下行添加到Nginx配置文件中完成的:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

此行告诉Nginx将客户端的IP地址添加到X-Forwarded-For头中。当请求被转发时,代理服务器将检查此头以提取客户端的真实IP地址。

以下是完整的Nginx配置文件示例:

server {
    listen 80;
    server_name example.com;
 
    access_log /var/log/nginx/example.access.log main;
    error_log /var/log/nginx/example.error.log;
 
    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

此配置将所有请求转发到本地主机上运行的HTTP服务器。每个传入请求都会添加一个X-Forwarded-For头并转发到9000端口。

3.2 PHP代码处理

以下是获取客户端真实IP地址的PHP代码:

function get_ip_address() {
    // Check for shared Internet/ISP IP
    if (!empty($_SERVER['HTTP_CLIENT_IP']) && validate_ip($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    }
 
    // Check for IP passed in via HTTP_X_FORWARDED_FOR header
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        // Check if multiple IP addresses exist in this header
        $ip_addresses = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
 
        foreach ($ip_addresses as $ip) {
            if (validate_ip($ip)) {
                return $ip;
            }
        }
    }
 
    // Check for IP passed in via REMOTE_ADDR header
    if (validate_ip($_SERVER['REMOTE_ADDR'])) {
        return $_SERVER['REMOTE_ADDR'];
    }
 
    // Return unreliable IP address since all else failed
    return $_SERVER['REMOTE_ADDR'];
}
 
function validate_ip($ip) {
    if (strtolower($ip) === 'unknown') {
        return false;
    }
 
    // Generate IPv4 network address
    $ipv4_network = ip2long('0.0.0.0/24');
 
    // Generate IPv6 network address
    $ipv6_network = inet_pton('::ffff:0.0.0.0') . '/96';
 
    // Check if IP address is IPv4
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
        // Convert IP to IPv4 network address
        $ip_network = ip2long($ip) & ~((1 << (32 - 24)) - 1);
 
        return $ip_network === $ipv4_network;
    }
 
    // Check if IP address is IPv6
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) {
        // Convert IP to IPv6 network address
        $ip_network = inet_pton($ip) & ~((1 << (128 - 96)) - 1);
 
        return $ip_network === $ipv6_network;
    }
 
    return false;
}

此代码使用3种方法来检测客户端的真实IP地址:

  1. 如果HTTP_CLIENT_IP头部存在且有效,则返回该IP地址。

  2. 如果HTTP_X_FORWARDED_FOR头部存在,则迭代其值,并返回第一个有效IP地址。

  3. 如果REMOTE_ADDR头部存在且有效,则返回该IP地址。

  4. 如果所有检查都失败,则返回REMOTE_ADDR头中的IP地址。

validate_ip()函数用于检查传递的IP地址是否有效。以下是它的工作原理:

  1. 检查地址是否为“unknown”。

  2. 生成IPv4和IPv6的网络地址。

  3. 检测IP地址是否为IPv4,并将其转换为网络地址。如果地址匹配IPv4网络地址,则返回true。

  4. 检测IP地址是否为IPv6,并将其转换为网络地址。如果地址匹配IPv6网络地址,则返回true。

总结

以上内容介绍了如何通过PHP结合Nginx实现获取用户真实IP地址。我们从了解了HTTP请求和代理服务器的工作原理出发,并讨论了X-Forwarded-For头的作用。最后演示了如何编写有效的PHP代码来获取客户端真实IP地址。
在这里插入图片描述
相信通过本文,你对获取用户真实IP地址有了更深入的理解,如果你有什么疑问或者建议,欢迎在下方评论区留言。后续更多内容将收录在专栏PHP快速入门与实战中,感谢大家支持。喜欢记得三联哟。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑夜开发者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值