为什么我应该将远程和转发存储为用户的 IP


Why should I store both REMOTE and FORWARDED as user's IP?

目前我得到usr的IP是这样的:

if ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) ){
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif ( isset($_SERVER['REMOTE_ADDR']) ) {
    $ip = $_SERVER['REMOTE_ADDR'];
}
// IPs
+----+----------------+-------------+
| id |    user_ip     |  date_time  |
+----+----------------+-------------+
| 1  | 43.12.9.9      | 1468070172  |
| 2  | 173.3.0.1      | 1468070667  |
+----+----------------+-------------+

但是现在,我在这里读到了这一点:

如果要保存$_SERVER['HTTP_X_FORWARDED_FOR'],请确保同时保存$_SERVER['REMOTE_ADDR']值。 例如,通过将两个值保存在数据库的不同字段中。

所以我将我的代码更改为:

$remote_add = $_SERVER['REMOTE_ADDR']; // I don't use isset() for this becase it is always set
$http_x_forwarded_for = isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : null;
// IPs
+----+----------------+----------------+-------------+
| id |    remote      |   forwarded    |  date_time  |
+----+----------------+----------------+-------------+
| 1  | 43.12.9.9      | NULL           | 1468070172  |
| 2  | 93.35.40.1     | 173.3.0.1      | 1468070667  |
+----+----------------+----------------+-------------+

好的,我正在做的是正确的吗?我问这个是因为一些专业程序员告诉我你做什么是无用的,你只需要列作为用户的IP。 好吧,请有人清理我吗?如何正确获取用户的 IP?


我的最终代码:

foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED') as $key){
  if (array_key_exists($key, $_SERVER) === true){
    foreach (explode(',', $_SERVER[$key]) as $header){
      $header = trim($header); // just to be safe
      if (filter_var($header, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
        $header = $header;
      }
    }
  }
}
$user_ip = $_SERVER['REMOTE_ADDR'];
// IPs
+----+----------------+----------------+-------------+
| id |    user_ip     |     header     |  date_time  |
+----+----------------+----------------+-------------+
| 1  | 43.12.9.9      | NULL           | 1468070172  |
| 2  | 93.35.40.1     | 173.3.0.1      | 1468070667  |
+----+----------------+----------------+-------------+

在 http-request 中,有人可以欺骗除远程地址之外的任何信息。如果没有实际访问该 IP 地址上的调制解调器或该调制解调器/路由器后面的计算机,则无法完成 tcp 握手。REMOTE_ADDR密钥始终设置为连接到服务器的设备。在某些情况下,该设备是用户使用的代理。

HTTP_X_FORWARDED_FOR 标头是一个标头,不错的代理使用它来表示原始 IP 地址是什么,该地址命令代理代表他们加载页面。但是,此标头可能是欺骗性的。有人可以发送此标头中的任何信息,包括有趣的内容,例如127.0.0.1(localhost),甚至是仅假定该字段只能包含数字和点的服务器的html或脚本,甚至是不使用准备好的查询插入这些内容的服务器的原始sql语句。


唯一保证正确的信息是远程 IP,但不一定是用户的 IP。如果远程 IP 是代理,则记录远程 IP 可能允许您联系欺诈行为的远程代理的所有者,让他们搜索实际发出该请求的 IP 的日志。在某些情况下,转发的 IP 可以在代理不打算掩盖使用代理的人的身份的情况下保护您的时间,这将允许您对该 IP 而不是代理本身采取一些措施。

有时使用 HTTP_X_FORWARDED_FOR 标头,有时使用 REMOTE_ADDR 进行有根据的猜测将导致数据不可用。您无法知道哪些数据可以信任,哪些数据可以信任。

我问这个是因为一些专业程序员告诉我你做什么是无用的,你只需要列作为用户的IP。

如果你正在做的事情是无用的,完全取决于你使用它的目的。如果要显示转发的字段,请记住正确转义显示该字段的上下文的所有特殊字符。如果您只存储一个 ip,它将是远程 ip,完全忽略HTTP_X_FORWARDED_FOR标头。这是您唯一可以完全信任的信息。