本文共 2033 字,大约阅读时间需要 6 分钟。
当需要获取用户真实IP地址时,开发者通常会遇到多种挑战,尤其是在涉及负载均衡、CDN或多层代理的情况下。以下是获取用户IP地址的常见方法以及防刷机制的实现方案。
在获取用户IP地址时,常用的方法包括:
REMOTE_ADDR:这是一个可靠的变量,表示最后与服务器握手的客户端IP地址。在单服务器环境下,它通常是用户的直接IP地址。然而,在负载均衡或反向代理的情况下,它可能是负载均衡节点的IP地址。
HTTP_X_FORWARDED_FOR(XFF):这是一个HTTP头字段,用于记录通过代理服务器转发的客户端IP地址。它通常包含多个IP地址,表示不同级别的代理。开发者需要从中提取第一个有效IP地址。
HTTP_CLIENT_IP:这是一个不常用的HTTP头字段,虽然在某些情况下可以获取客户端IP地址,但它不是一个标准化的字段,不同服务器对其支持情况不同。
为了确保获取到真实客户端IP地址,建议优先使用REMOTE_ADDR,然后作为补充使用HTTP_X_FORWARDED_FOR。然而,在负载均衡环境中,直接使用REMOTE_ADDR可能无法获取到真实客户端IP地址,因此需要通过负载均衡节点将客户端IP地址传递给服务器。
X-Forwarded-For:用于记录经过多级代理的客户端IP地址。每经过一个代理服务器,该IP地址会被追加。它是一个标准化的字段,适用于多层代理环境。
X-Real-IP:这是一个非标准化的字段,值在不同代理环境中可能不一致。因此,优先使用X-Forwarded-For来获取客户端IP地址。
为了防止IP注入攻击,建议在获取IP地址后对其进行合法性验证。以下是一个常用的验证方法:
$ip = getClientIp();$long = sprintf("%u", ip2long($ip));$ip = ($long ? array($ip, $long) : array('0.0.0.0', 0)); 此外,为了防止频繁访问或刷机,建议在获取IP地址后实施频率限制。以下是一个常用的频率检查方法:
public static function frequencyCheckWithTimesInCache($id, $second, $times) { $value = Yii::app()->cache->get($id); if (!$value) { $data[] = time(); Yii::app()->cache->set($id, json_encode($data), $second); return true; } $data = json_decode($value, true); if (count($data) + 1 <= $times) { $data[] = time(); Yii::app()->cache->set($id, json_encode($data), $second); return true; } if (time() - $data[0] > $second) { array_shift($data); $data[] = time(); Yii::app()->cache->set($id, json_encode($data), $second); return true; } return false;} 例如,以下代码用于限制每小时请求不超过50次:
if (!frequencyCheckWithTimesInCache('times_uid_' . $uid, 3600, 50)) { return '请求过于频繁';} 此外,为了防止刷机,可以对设备号进行限制。例如:
if (!empty($deviceId)) { $deviceUseChance = Yii::db()->createCommand() ->select('count(id)') ->from('activity00167_log') ->where('device_id = :deviceId', ['deviceId' => $deviceId]) ->queryScalar(); $deviceChance = 3 - $deviceUseChance;} 通过以上方法,可以有效防止IP注入攻击和刷机行为,同时确保用户的访问频率在合理范围内。
转载地址:http://rotfk.baihongyu.com/