【问题标题】:PHP IPv4 and IPv6 function to store in a databasePHP IPv4 和 IPv6 函数存储在数据库中
【发布时间】:2013-07-03 00:47:44
【问题描述】:

我想将 IP 地址与用户注册、帖子、上传等一起存储。我以前创建的网站一直使用 ip2long/long2ip 并将其存储为 UNSIGNED INT,因为 IPv4 是我唯一关心的问题。所以我会通过ip2long 运行IP 地址,存储它,当我检索它时,使用long2ip。但现在我想确保它更具未来性,并同时处理 IPv4 和 IPv6。

这是我迄今为止提出的用于处理 IPv4 和 IPv6 的函数:

function ipCheck()
{
    // Get IP Address
        if (!empty($_SERVER['HTTP_CLIENT_IP'])) // Shared client
        {
            $ipAddress = $_SERVER['HTTP_CLIENT_IP'];
        }
        else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) // Proxy address
        {
            $ipAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
        else
        {
            $ipAddress = $_SERVER['REMOTE_ADDR']; // User viewing
        }

    // Over IP for testing
        /*
            IP Examples for testing

            IPv4:   64.233.160.0
            IPv6:   2607:f0d0:1002:51::4
            IPv6:   2607:f0d0:1002:0051:0000:0000:0000:0004
        */

        $ipAddress = '2607:f0d0:1002:0051:0000:0000:0000:0004'; // Comment out this line for actual IP

    // Validate IP
        if (filter_var($ipAddress, FILTER_VALIDATE_IP))
        {
            if (strpos($ipAddress, ':') !== false)
            {
                $ipType = 'IPv6';
                $ipAddressDB = inet_pton($ipAddress);
            }
            else
            {
                $ipType = 'IPv4';
                $ipAddressDB = ip2long($ipAddress);
            }
        }
        else
        {
            $ipType = 'Invalid';
            $ipAddressDB = $ipAddress;
        }

    // Display results
        echo '<strong>IP Type: </strong>'.$ipType.'<br />',
             '<strong>IP Address: </strong>'.$ipAddress.'<br />',
             '<strong>DatabaseIP: </strong>'.$ipAddressDB;
}

ipCheck();

我个人没有 IPv6 地址,因此我覆盖了 $ipAddress 变量以进行测试。

对于 IPv4 地址一切正常,但对于 IPv6 地址,$ipAddressDB 在我使用 2607:f0d0:1002:0051:0000:0000:0000:0004 测试 IP 时返回值 &amp;(diamond-with-question-mark)(diamond-with-question-mark)Q,我真的不知道为什么?我使用inet_pton 错了吗?我必须添加一些东西吗?是不是因为测试IPv6地址?

我假设一旦我开始工作,因为我们需要存储在 2 列中,我为数据库 IP 创建 2 个变量,如果它是 IPv4,我将它分配给变量 1 并将变量 2 留空。然后如果是 IPv6,我将它拆分,将前半部分放在变量 1 中,将第二部分放在变量 2 中。然后在插入/选择时,如果第二列为空,我们可以假设它是 IPv4 地址?

我什至不能 100% 确定我正在尝试做的事情是否真的可行?如果不是,最好直接采用 IPv6 地址(不带inet_pton),然后按这种方式拆分它们吗?

【问题讨论】:

  • 你需要ip地址做什么?您可以信任的唯一变量是$_SERVER['REMOTE_ADDR']。其他的都是垃圾。
  • 我能问一下为什么其他人都是垃圾吗? (严肃的问题)
  • 因为发件人可以将任何东西放在那里(并且只有REMOTE_ADDR 由网络服务器从连接信息中填充(也可以忘记,但是发件人不会检索回响应) ))
  • 因此,在函数开头为HTTP_* 废弃ifelse 并坚持使用REMOTE_ADDR。谢谢你的建议!关于主要问题的任何线索?为什么inet_pton 返回这么奇怪的值?
  • 附带说明,您的ipCheck() 函数可能会通过在请求中添加X-Forwarded-For: myfakeip 标头来“欺骗”IP 地址。

标签: php mysql ipv6 ipv4


【解决方案1】:

您正在查看二进制形式的地址。 “&”为UTF-8 0x26,0xf0和0xd0为无效UTF-8(显示为“�”),“Q”为UTF-8 0x51,其他字节为空显示。在存储之前将字节串编码为十六进制(然后您可以以完全相同的方式处理 IPv4 地址)。

【讨论】:

  • 喜欢这个? $ipAddressBin2Hex = bin2hex($ipAddress); $ipAddressDB = inet_pton($ipAddressBin2Hex); 如有错误请见谅!
  • 正如你提到的编码,它让我思考,这是否与我设置meta 标签charset 属性有关。我通常使用&lt;meta charset="utf-8"&gt;,所以我通过设置它并将函数放在&lt;body&gt; 中来测试它。然后创建了一个新页面,除了我的 ipCheck() 函数之外什么都没有,并且任一页面上的值都不同。我按照上面写的方式尝试了bin2hex 函数,我收到了Warning: inet_pton() [function.inet-pton]: Unrecognized address...
猜你喜欢
  • 2012-05-22
  • 2013-03-18
  • 1970-01-01
  • 2016-01-17
  • 2011-01-04
  • 2021-11-08
  • 2016-09-18
  • 2011-07-19
  • 1970-01-01
相关资源
最近更新 更多