Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
完成PHP+;MySQL IPv4&;IPv6解决方案?_Php_Mysql_Ipv6_Ipv4 - Fatal编程技术网

完成PHP+;MySQL IPv4&;IPv6解决方案?

完成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位无符号整数字段。对我来说,这使得搜索某些网络变得简单,尽管我

我对网络主题不是很了解,但我必须为我的项目存储IP地址,我想准备好处理IPv4和IPv6。我读过的最好的解决方案似乎是两个BIGINT无符号字段,其中一个在IPv4中为空:
有人有完整的解决方案吗

我需要将代码从字符串地址(如$服务器['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
}