完成PHP+;MySQL IPv4&;IPv6解决方案?
我对网络主题不是很了解,但我必须为我的项目存储IP地址,我想准备好处理IPv4和IPv6。我读过的最好的解决方案似乎是两个BIGINT无符号字段,其中一个在IPv4中为空:完成PHP+;MySQL IPv4&;IPv6解决方案?,php,mysql,ipv6,ipv4,Php,Mysql,Ipv6,Ipv4,我对网络主题不是很了解,但我必须为我的项目存储IP地址,我想准备好处理IPv4和IPv6。我读过的最好的解决方案似乎是两个BIGINT无符号字段,其中一个在IPv4中为空: 有人有完整的解决方案吗 我需要将代码从字符串地址(如$服务器['HTTP\U客户端\U IP']生成)转换为数值,反之亦然 非常感谢你的帮助。我想确保我做得正确。我实际上是按照人类写序号的方式来存储序号的。因此,IPv6有8个16位无符号整数字段,IPv4有4个8位无符号整数字段。对我来说,这使得搜索某些网络变得简单,尽管我
有人有完整的解决方案吗 我需要将代码从字符串地址(如$服务器['HTTP\U客户端\U IP']生成)转换为数值,反之亦然
非常感谢你的帮助。我想确保我做得正确。我实际上是按照人类写序号的方式来存储序号的。因此,IPv6有8个16位无符号整数字段,IPv4有4个8位无符号整数字段。对我来说,这使得搜索某些网络变得简单,尽管我可以看到2个未签名的bigint也很简单 或者,您可以将其存储为代码中最常用的格式,并将其作为一种格式进行检索。这似乎是一个字符串,大约40个字符长。如果这样做,您将希望使用中建议的规范表示
我不能只为你写转换代码;您需要提供一些示例,说明您尝试的哪些方法不起作用,以及原因。或者您可以使用类似PostgreSQL的数据库,如果这是一个选项的话。它具有用于存储和搜索IPv4和IPv6地址和前缀的本机数据类型。输入和输出以字符串表示(通常) 如果您必须使用MySQL,这实际上取决于您希望如何使用这些地址。如果要搜索子网、按前缀分组等,则整数是最有用的。如果您只需要存储它们,那么varchar就是一个不错的选择。对于IP地址(格式)验证,我目前正在使用它作为我正在进行的工作的一部分-目前还不能100%确定它是否完全正确-需要向它抛出更多数据(我也不喜欢我在私有成员上使用的命名约定——但这是重构的一个简单修复方法):
类IP地址{
//IP地址字符串
私人$ip_地址;
//IPv4验证(RegExp插入)
私有$match_ipv4;
//IPv6验证(RegExp插入)
私有$match_ipv6;
/**
*构造函数
*
*$sIPAddress参数是可选的-
*它允许您在中设置IP地址
*创建时的对象。
*
*@param string$sIPAddress
*@返回无效
*/
公共函数构造($sIPAddress=null){
//设置regexp插入
//IPv4十进制八位字节匹配
$sDecOctet=“([0-9]|[1-9][0-9]| 1[0-9][0-9]| 2[0-4][0-9]| 25[0-5])”;
//IPv4匹配
$this->match_ipv4=“({$sDecOctet}\){3}{$sDecOctet}”;
//十六进制匹配
$sH16=“[0-9a-fA-F]{1,4}”;
//字符32匹配
$sLS32=“({$sH16}:{$sH16}{$this->match_ipv4})”;
//IPv6匹配
$this->match_ipv6=“(({$sH16}:){6}”
.“|::({$sH16}:){5}”
.“|({$sH16})::({$sH16}:){4}”
.“({$sH16}:){0,1}{$sH16})?::({$sH16}:){3}”
.“({$sH16}:){0,2}{$sH16})?::({$sH16}:){2}”
.“|(({$sH16}:){0,3}{$sH16})?:{$sH16}:”
.“|(({$sH16}:){0,4}{$sH16})?:”
.“{$sLS32}”
.“|((({$sH16}:){0,5}{$sH16})?:{$sH16}”
.“|(({$sH16}:){0,6}{$sH16})?:”
. "))";
//如果需要,请设置IP地址
如果(!为null($sIPAddress)){
$this->setIPAddress($sIPAddress);
}
}
/**
*IP地址设置器
*
*设置IP地址字符串-这可以
*可以是IPv4或IPv6格式。
*
*@param string$sIPAddress
*@返回无效
*/
公共函数setIPAddress($sIPAddress){
$this->ip_address=$sIPAddress;
}
/**
*IP地址获取器
*
*返回IP地址字符串-此
*可以是IPv4或IPv6格式。
*
*@返回字符串
*/
公共函数getIPAddress(){
返回$this->ip\u地址;
}
/**
*IPv4正则表达式获取程序
*
*返回用于
*验证IPv4地址。
*
*@返回字符串
*/
公共函数getIPv4RegExp(){
返回“/^”。$this->match_ipv4.$/”;
}
/**
*IPv6正则表达式获取程序
*
*返回用于
*验证IPv6地址。
*
*@返回字符串
*/
公共函数getIPv6RegExp(){
返回“/^”。$this->match_ipv6.$/i”;
}
/**
*IPv4验证
*
*验证存储的IP地址
*针对IPv4模式和返回
*一个布尔值,表示地址
*是否为IPv4格式。
*
*@returnbool
*/
公共函数validateIPv4(){
返回ip2long($this->ip_地址)&&ip2long($this->ip_地址)!=-1?真:假;
}
/**
*IPv6验证
*
*验证存储的IP地址
*针对IPv6模式和返回
*一个布尔值,表示地址
*是否为IPv6格式。
*
*@returnbool
*/
公共函数validateIPv6(){
返回preg_match($this->getIPv6RegExp(),$this->ip_地址)?true:false;
}
/**
*一般有效性检查
*
*根据存储的IP地址验证存储的IP地址
*IPv4和IPv6模式-如果
*返回两个匹配项中的任意一个,然后返回true
*(这是一个格式正确的IP地址)。
*
*否则它不是一个有效的IP地址
*返回false。
*
*@returnbool
*/
公共函数isValid(){
返回$this->validateIPv4()| |$this->validateIPv6()?true:false;
}
/**
*保留状态检查器
*
*此方法检查存储的IP地址是否正确
*是本地网络范围的一部分(即在
*专用保留IP地址范围)
*
*返回一个表示此保留状态的布尔值
*除非IP地址本身无效-其中
*返回大小写null。
*
*@returnbool
*/
保留公共职能(){
//IPv4格式
如果($this->validateIPv4()){
返回$this->\u getIPv4IsReserved($this->ip\u地址);
}
//IPv6格式
elseif($this->validateIPv6()){
//IPv4屏蔽
//如果
class IPAddress {
//IP Address string
private $ip_address;
//IPv4 verification (RegExp insert)
private $match_ipv4;
//IPv6 verification (RegExp insert)
private $match_ipv6;
/**
* Constructor function
*
* The $sIPAddress parameter is optional -
* it allows you to set the IP address in
* the object at creation.
*
* @param string $sIPAddress
* @return void
*/
public function __construct($sIPAddress=null) {
//setup regexp inserts
//IPv4 decimal octets match
$sDecOctet = "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])";
//IPv4 match
$this->match_ipv4 = "({$sDecOctet}\.){3}{$sDecOctet}";
//Hex 16 match
$sH16 = "[0-9a-fA-F]{1,4}";
//Char32 match
$sLS32 = "({$sH16}:{$sH16}|{$this->match_ipv4})";
//IPv6 match
$this->match_ipv6 = "((({$sH16}:){6}"
. "|::({$sH16}:){5}"
. "|({$sH16})?::({$sH16}:){4}"
. "|(({$sH16}:){0,1}{$sH16})?::({$sH16}:){3}"
. "|(({$sH16}:){0,2}{$sH16})?::({$sH16}:){2}"
. "|(({$sH16}:){0,3}{$sH16})?::{$sH16}:"
. "|(({$sH16}:){0,4}{$sH16})?::"
. "){$sLS32}"
. "|((({$sH16}:){0,5}{$sH16})?::{$sH16}"
. "|(({$sH16}:){0,6}{$sH16})?::"
. "))";
//set the IP address if required
if(!is_null($sIPAddress)) {
$this->setIPAddress($sIPAddress);
}
}
/**
* IP Address setter
*
* Sets the IP address string - this can
* be either IPv4 or IPv6 format.
*
* @param string $sIPAddress
* @return void
*/
public function setIPAddress($sIPAddress) {
$this->ip_address = $sIPAddress;
}
/**
* IP Address getter
*
* Returns the IP address string - this
* can be either IPv4 or IPv6 format.
*
* @return string
*/
public function getIPAddress() {
return $this->ip_address;
}
/**
* IPv4 RegExp getter
*
* Returns Regular Expression used to
* validate IPv4 addresses.
*
* @return string
*/
public function getIPv4RegExp() {
return '/^' . $this->match_ipv4 . '$/';
}
/**
* IPv6 RegExp getter
*
* Returns the Regular Expression used to
* validate IPv6 addresses.
*
* @return string
*/
public function getIPv6RegExp() {
return '/^' . $this->match_ipv6 . '$/i';
}
/**
* IPv4 validation
*
* Validates the stored IP address
* against the IPv4 pattern and returns
* a boolean denoting whether the address
* if of IPv4 format or not.
*
* @return bool
*/
public function validateIPv4() {
return ip2long($this->ip_address) && ip2long($this->ip_address) !== -1 ? true : false;
}
/**
* IPv6 validation
*
* Validates the stored IP address
* against the IPv6 pattern and returns
* a boolean denoting whether the address
* if of IPv6 format or not.
*
* @return bool
*/
public function validateIPv6() {
return preg_match($this->getIPv6RegExp(), $this->ip_address) ? true : false;
}
/**
* General validity check
*
* Validates the stored IP address against
* both the IPv4 and IPv6 patterns - if
* EITHER matches then true is returned
* (it's a correctly formatted IP address).
*
* Otherwise it's not a valid IP address
* and false is returned.
*
* @return bool
*/
public function isValid() {
return $this->validateIPv4() || $this->validateIPv6() ? true : false;
}
/**
* Reserved state checker
*
* This method checks wheter the stored IP address
* is part of the local network range (i.e. it's in
* the private reserved IP address range)
*
* A boolean is returned denoting this reserved state
* unless the IP address itself is invalid - in which
* case null is returned.
*
* @return bool
*/
public function isReserved() {
//IPv4 format
if($this->validateIPv4()) {
return $this->_getIPv4IsReserved($this->ip_address);
}
//IPv6 format
elseif($this->validateIPv6()) {
//IPv4 masking
// this falls over if the IPv4 part is short-handed
// for instance ::ffff:192.0.2.128 can be written as ::ffff:c000:280
$reIPv4Masking = '/^((0{1,4}:){6}|(0{1,4}:){1,5}ffff:|::ffff:)(([0-9]{1,3}\.){3}[0-9]{1,3})/';
//standard reserved IPv6 addresses
//local loopback = 0:0:0:0:0:0:0:1 || ::1
if(preg_match('/^(0{1,4}:){1,7}1|::1|fc00:.*$/i', $this->ip_address)) {
return true;
}
//if this is really an IPv4 address stacked in IPv6...
elseif(preg_match($reIPv4Masking, $this->ip_address)) {
$sIPv4Address = preg_replace($reIPv4Masking, "$2", $this->ip_address);
return $this->_getIPv4IsReserved($sIPv4Address);
}
//not reserved
else {
return false;
}
}
//invalid format
else {
return null;
}
}
/**
* IPv4 reserved state checker
*
* Private method to determine whether an IPv4 address is in
* one of the reserved private brackets (e.g. it's probably local)
*
* Returns a boolean denoting whether it's a reserved IPv4 address
* or null should the IP address fail validation
*
* @param string $sIPv4Address
* @return bool
*/
private function _getIPv4IsReserved($sIPv4Address) {
$sIP = long2ip(ip2long($sIPv4Address));
$reIPv4 = '/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/$'; //just a quick and dirty RegExp without sanity checking since we've already done that
if(preg_match($reIPv4, $sIP)) {
//break the IP address into parts and cast to integers
$iIPp1 = VParse::toInt(preg_replace($reIPv4, "$1", $sIP));
$iIPp2 = VParse::toInt(preg_replace($reIPv4, "$2", $sIP));
$iIPp3 = VParse::toInt(preg_replace($reIPv4, "$3", $sIP));
$iIPp4 = VParse::toInt(preg_replace($reIPv4, "$4", $sIP));
//check for reserved IP addresses
// 127.0.0.1 (local loopback)
// 10.0.0.0 - 10.255.255.255
// 172.16.0.0 - 172.31.255.255
// 192.168.0.0 - 192.168.255.255
if( ($iIPp1 == 127 && $iIPp2 == 0 && $iIPp3 == 0 && $iIPp4 == 1) || $iIPp1 == 10 || ($iIPp1 == 172 && $iIP2 >= 16 && $iIP2 <= 31) || ($iIPp1 == 192 && $iIPp2 == 168) ) {
return true;
}
//not part of the standard private IP address ranges
else {
return false;
}
}
//invalid format
else {
return null;
}
}
//end class
}