在UNKNOWN DB中存储IPv6的最佳方法?

时间:2013-01-20 18:15:00

标签: database store ipv6 abstract

我知道这个问题已被问过很多次,但我无法找到最终的解决方案;所以这里:

如何在不知道数据库的情况下,在数据库中使用最佳实践存储IP(IPv4和IPv6)?这用于数据库抽象目的,例如PHP PDO。

小调,我有PHP 5.2.17,因为我在Windows上需要PEAR。

人们一直建议将它存储为varbinary(16)并使用mysql函数inet6_ntop和inet6_pton来传递IP作为字符串来回传递;像Extending MySQL 5 with IPv6 functions建议的那样。在PHP中,函数inet_pton()和inet_ntop()可以在ThiefMaster中将IPv4和IPv6来回转换为二进制格式this question is suggesting,但是不清楚如何将二进制内容传递给SQL INSERT / UPDATE字符串(这些php函数仅与php 5.3.0 on windows一起提供,即使可以对它们进行反向工程)。我真的很喜欢Jake所做的事情和his results with regards to integer representations of IPs in DBs,如果我要将这个实现到我的数据库中,这可能会在一些遥远的,无法预料的未来派上用场,但后来我对数据库不确定使用PHP PDO进行数据库抽象的交叉兼容性。 This post似乎提供了关于存储二进制值的一个接近的答案,但是不能将未转义的二进制注入字符串作为潜在的危险吗?另外,如果您遵循这条路线,如果某些开发人员想要快速查找,有多少DB可以将varbinary(16)/ int(128bit)转换为代表性IP?

在我看来,最简单的方法是将ip string as-is插入varchar(45)。但是那些想要使用inet_ntop()和inet_pton()函数在PHP(逆向工程as djmaze(AT)dragonflycms(.)orgMagicalTux at FF dot st建议)中遵循复杂路径的人,如何存储和检索IPv6为二进制?有人可以使用来自<?php $strIP = "2001:4860:b002::68"; ?>的PDO,使用INSERT然后使用SELECT预处理语句来提供示例吗?

正如你所看到的,我已经完成了我的研究,但这个IPv6的终极良好实践对我来说并不清楚。

1 个答案:

答案 0 :(得分:2)

与您的研究表明一样,将IP地址存储为规范形式的字符串,二进制字符串或整数是有好处和问题的。也许存在将IP地址存储在数据库中的中间地带。

如何将它们存储为字符串,但扩展到完整的最大长度。这样你仍然可以比较它们(==,&gt;,&lt;等等),但它们仍然可读,你不需要特殊字符的特殊输入和输出编码。

如何执行此操作的示例:

function expand_ip_address($addr_str) {
  /* First convert to binary, which also does syntax checking */
  $addr_bin = @inet_pton($addr_str);
  if ($addr_bin === FALSE) {
    return FALSE;
  }

  /* Then differentiate between IPv4 and IPv6 */
  if (strlen($addr_bin) == 4) {
    /* IPv4: print each byte as 3 digits and add dots between them */
    return implode('.', array_map(
      create_function('$byte', 'return sprintf("%03d", ord($byte));'),
      str_split($addr_bin)
    ));
  } else {
    /* IPv6: print as hex and add colons between each group of 4 hex digits */
    return implode(':', str_split(bin2hex($addr_bin), 4));
  }
}

还有一些例子:

/* Test IPv4 */
var_dump(expand_ip_address('192.0.2.55'));

/* Test IPv6 */
var_dump(expand_ip_address('2001:db8::abc'));

/* Test invalid */
var_dump(expand_ip_address('192:0:2:55'));

哪种产品:

string(15) "192.000.002.055"
string(39) "2001:0db8:0000:0000:0000:0000:0000:0abc"
bool(false)