【问题标题】:How can I detect if the user is on localhost in PHP?如何检测用户是否在 PHP 中的本地主机上?
【发布时间】:2011-01-04 10:12:37
【问题描述】:

换句话说,我如何判断使用我的 Web 应用程序的人是否在它所在的服务器上?如果我没记错的话,PHPMyAdmin 出于安全原因会这样做。

【问题讨论】:

    标签: php localhost detection


    【解决方案1】:

    $_SERVER["REMOTE_ADDR"] 应该告诉你用户的 IP。不过,这是欺骗性的。

    查看this bounty question 以获得非常详细的讨论。

    我认为您对 PHPMyAdmin 的记忆有所不同:出于安全原因,许多 MySQL 服务器都被配置为只能从 localhost 访问它们。

    【讨论】:

    • 值得注意的是,一些 MySQL 服务器是通过不绑定到公共接口来配置的。同样,如果您想以相同的方式限制 PHP 应用程序,您应该考虑通过仅绑定到内部接口的 apache 实例来提供它。
    【解决方案2】:

    您也可以使用$_SERVER['REMOTE_ADDR'],其请求的客户端的 IP 地址由 Web 服务器提供。

    $whitelist = array(
        '127.0.0.1',
        '::1'
    );
    
    if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
        // not valid
    }
    

    【讨论】:

    • 这实际上比欺骗 IP 更容易破解。你真的应该改变它。
    • @skcin7 可能是您的服务器设置。检查一下。
    • @Pekka웃 您可以发送例如Host: 127.0.0.1,它会被填充到HTTP_HOST,所以它根本不是可靠的方法。
    • 是的,这是个糟糕的建议,并且以目前的形式,需要编辑 - 或否决。
    • 不要忘记 IPv6:$whitelist = array('127.0.0.1', '::1');
    【解决方案3】:

    看来你不应该使用$_SERVER['HTTP_HOST'],因为这是http头中的值,很容易伪造。

    您也可以使用$_SERVER["REMOTE_ADDR"],这是更安全的值,但也可以伪造。这个remote_addr是Apache返回结果的地址。

    【讨论】:

    • REMOTE_ADDR 是可以伪造的,但是如果您想将其伪装成127.0.0.1::1,则需要破坏机器,其中欺骗REMOTE_ADDR 是您的最少担心。相关答案-stackoverflow.com/a/5092951/3774582
    【解决方案4】:

    较新的操作系统用户(Win 7、8)也可能会发现有必要在其白名单数组中包含 IPV6 格式的远程地址:

    $whitelist = array('127.0.0.1', "::1");
    
    if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
        // not valid
    }
    

    【讨论】:

      【解决方案5】:

      作为补充,作为功能......

      function isLocalhost($whitelist = ['127.0.0.1', '::1']) {
          return in_array($_SERVER['REMOTE_ADDR'], $whitelist);
      }
      

      【讨论】:

      • 作为一种好的做法,我建议添加“else return false;”以便该函数始终返回一个布尔值。或者,只需完全删除“if”,而是“return in_array($_SERVER['REMOTE_ADDR'], $whitelist);”
      【解决方案6】:

      如果您想拥有一个支持静态 IP动态名称白名单/白名单

      例如:

      $whitelist = array("localhost", "127.0.0.1", "devel-pc.ds.com", "liveserver.com");
      if (!isIPWhitelisted($whitelist)) die();
      

      通过这种方式,您可以设置能够(肯定)被检测到的名称/IP列表。动态名称增加了从不同点访问的灵活性。

      您有两个常用选项,您可以在本地主机文件中设置一个名称,也可以只使用一个可以在任何地方找到的动态名称提供程序

      这个函数会缓存结果,因为 gethostbyname 是一个非常慢的函数。

      为此,我实现了这个功能:

      function isIPWhitelisted($whitelist = false)
      {
          if ( isset($_SESSION) && isset($_SESSION['isipallowed']) )
              { return $_SESSION['isipallowed'];  }
      
          // This is the whitelist
          $ipchecklist = array("localhost", "127.0.0.1", "::1");
          if ($whitelist) $ipchecklist = $whitelist;
      
          $iplist = false;
          $isipallowed = false;
      
          $filename = "resolved-ip-list.txt";
          $filename = substr(md5($filename), 0, 8)."_".$filename; // Just a spoon of security or just remove this line
      
          if (file_exists($filename))
          {
              // If cache file has less than 1 day old use it
              if (time() - filemtime($filename) <= 60*60*24*1)
                  $iplist = explode(";", file_get_contents($filename)); // Read cached resolved ips
          }
      
          // If file was not loaded or found -> generate ip list
          if (!$iplist)
          {
              $iplist = array(); $c=0;
              foreach ( $ipchecklist as $k => $iptoresolve )
              {
                  // gethostbyname: It's a VERY SLOW function. We really need to cache the resolved ip list
                  $ip = gethostbyname($iptoresolve);
                  if ($ip != "") $iplist[$c] = $ip;
                  $c++;
              }
      
              file_put_contents($filename, implode(";", $iplist));
          }
      
          if (in_array($_SERVER['REMOTE_ADDR'], $iplist)) // Check if the client ip is allowed
              $isipallowed = true;
      
          if (isset($_SESSION)) $_SESSION['isipallowed'] = $isipallowed;
      
          return $isipallowed;
      }
      

      为了获得更好的可靠性,您可以将 $_SERVER['REMOTE_ADDR'] 替换为 @Pekka 在他的 post 中提到的 get_ip_address()"这个赏金问题”

      【讨论】:

      • 我不知道为什么有人给我的答案打了一个负分,而它显然提供了动态名称解析,而其他人则没有。 DNS 解析很慢,这就是需要缓存解析的原因。
      【解决方案7】:

      我找到了一个简单的答案。

      因为所有本地驱动器都有 C: 或 D: 或 F: ...等。

      只需检测第二个字符是否为:

      if ( substr_compare(getcwd(),":",1,1) == 0)
      {
      echo '<script type="text/javascript">alert(" The working dir is at the local computer ")</script>';
          $client_or_server = 'client';
      }
      else
      {
      echo '<script type="text/javascript">alert(" The working dir is at the server ")</script>';
          $client_or_server = 'server';
      }
      

      【讨论】:

      • 此解决方案似乎很容易出错,并且仅适用于 Windows。
      【解决方案8】:

      如何比较$_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR']以确定客户端是否与服务器在同一台机器上?

      【讨论】:

      • $_SERVER['SERVER_ADDR'] 并不总是可靠地返回服务器地址,例如,如果使用负载均衡器,它会返回我相信的负载均衡器的 IP 地址。
      【解决方案9】:

      我很抱歉,但所有这些答案对我来说似乎都很糟糕。我建议重新表述这个问题,因为从某种意义上说,所有机器都是“本地主机”。

      问题应该是;如何根据执行的机器运行不同的代码路径。

      在我看来,最简单的方法是创建一个名为 DEVMACHINE 的文件或您真正想要的任何文件,然后简单地检查

      file_exists('DEVMACHINE')

      上传到直播托管环境时记得排除这个文件!

      此解决方案不依赖于网络配置,不会被欺骗,并且可以轻松地在运行“live-code”和“dev-code”之间切换。

      【讨论】:

        【解决方案10】:

        使用了这个简单的 PHP 条件

        if($_SERVER['HTTP_HOST'] == 'localhost')
        {
            die('Localhost');
        }
        

        【讨论】:

          猜你喜欢
          • 2016-11-22
          • 2011-06-02
          • 1970-01-01
          • 1970-01-01
          • 2012-09-09
          • 1970-01-01
          • 1970-01-01
          • 2011-10-23
          相关资源
          最近更新 更多