本文翻译自:How to get the client IP address in PHP [duplicate]
This question already has an answer here: 这个问题已经在这里有了答案:
How can I get the client IP address using PHP? 如何使用PHP获取客户端IP地址?
I want to keep record of the user who logged into my website through his/her IP address. 我想保留通过其IP地址登录到我的网站的用户的记录。
#1楼
参考:https://stackoom.com/question/CbFp/如何在PHP中获取客户端IP地址-重复
#2楼
This is the method that I use, and it validates an IPv4 input: 这是我使用的方法,它可以验证IPv4输入:
// Get user IP address
if ( isset($_SERVER['HTTP_CLIENT_IP']) && ! empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) && ! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip = (isset($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
}
$ip = filter_var($ip, FILTER_VALIDATE_IP);
$ip = ($ip === false) ? '0.0.0.0' : $ip;
#3楼
My favourite solution is the way Zend Framework 2 uses. 我最喜欢的解决方案是Zend Framework 2的使用方式。 It also considers the $_SERVER
properties HTTP_X_FORWARDED_FOR
, HTTP_CLIENT_IP
, REMOTE_ADDR
but it declares a class for it to set some trusted proxies and it returns one IP address not an array. 它还考虑了$_SERVER
属性HTTP_X_FORWARDED_FOR
, HTTP_CLIENT_IP
, REMOTE_ADDR
但是它声明了一个用于设置某些受信任代理的类,并且返回一个IP地址而不是数组。 I think this is the solution that comes closest to it: 我认为这是最接近的解决方案:
class RemoteAddress
{
/**
* Whether to use proxy addresses or not.
*
* As default this setting is disabled - IP address is mostly needed to increase
* security. HTTP_* are not reliable since can easily be spoofed. It can be enabled
* just for more flexibility, but if user uses proxy to connect to trusted services
* it's his/her own risk, only reliable field for IP address is $_SERVER['REMOTE_ADDR'].
*
* @var bool
*/
protected $useProxy = false;
/**
* List of trusted proxy IP addresses
*
* @var array
*/
protected $trustedProxies = array();
/**
* HTTP header to introspect for proxies
*
* @var string
*/
protected $proxyHeader = 'HTTP_X_FORWARDED_FOR';
// [...]
/**
* Returns client IP address.
*
* @return string IP address.
*/
public function getIpAddress()
{
$ip = $this->getIpAddressFromProxy();
if ($ip) {
return $ip;
}
// direct IP address
if (isset($_SERVER['REMOTE_ADDR'])) {
return $_SERVER['REMOTE_ADDR'];
}
return '';
}
/**
* Attempt to get the IP address for a proxied client
*
* @see http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10#section-5.2
* @return false|string
*/
protected function getIpAddressFromProxy()
{
if (!$this->useProxy
|| (isset($_SERVER['REMOTE_ADDR']) && !in_array($_SERVER['REMOTE_ADDR'], $this->trustedProxies))
) {
return false;
}
$header = $this->proxyHeader;
if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
return false;
}
// Extract IPs
$ips = explode(',', $_SERVER[$header]);
// trim, so we can compare against trusted proxies properly
$ips = array_map('trim', $ips);
// remove trusted proxy IPs
$ips = array_diff($ips, $this->trustedProxies);
// Any left?
if (empty($ips)) {
return false;
}
// Since we've removed any known, trusted proxy servers, the right-most
// address represents the first IP we do not know about -- i.e., we do
// not know if it is a proxy server, or a client. As such, we treat it
// as the originating IP.
// @see http://en.wikipedia.org/wiki/X-Forwarded-For
$ip = array_pop($ips);
return $ip;
}
// [...]
}
See the full code here: https://raw.githubusercontent.com/zendframework/zend-http/master/src/PhpEnvironment/RemoteAddress.php 在此处查看完整的代码: https : //raw.githubusercontent.com/zendframework/zend-http/master/src/PhpEnvironment/RemoteAddress.php
#4楼
Here is a cleaner code sample of a good way to get the IP address of the user. 这是一个更干净的代码示例,它是获取用户IP地址的好方法。
$ip = $_SERVER['HTTP_CLIENT_IP'] ? $_SERVER['HTTP_CLIENT_IP'] : ($_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']);
Here is a shorter version that uses the elvis operator: 这是使用elvis运算符的较短版本:
$_SERVER['HTTP_CLIENT_IP'] ? : ($_SERVER['HTTP_X_FORWARDED_FOR'] ? : $_SERVER['REMOTE_ADDR']);
Here is a version that uses isset to remove notices (thank you, @shasi kanth): 这是使用isset删除通知的版本(谢谢@shasi kanth):
$ip = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
#5楼
Like the following? 像下面吗?
if (($ip=filter_input(INPUT_SERVER, 'REMOTE_ADDR', validate_ip)) === false or empty($ip)) {
exit;
}
echo $ip;
PS 聚苯乙烯
if (($ip=filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP|FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE)) === false) {
header('HTTP/1.0 400 Bad Request');
exit;
}
All headers beginning with 'HTTP_' or 'X-' may be spoofed, respectively is user defined. 可以欺骗所有以“ HTTP_”或“ X-”开头的标头,分别由用户定义。 If you want to keep track, use cookies, etc. 如果您想跟踪,请使用Cookie等。
#6楼
The following is the most advanced method I have found, and I have already tried some others in the past. 以下是我找到的最高级的方法,并且我过去已经尝试过其他方法。 It is valid to ensure to get the IP address of a visitor (but please note that any hacker could falsify the IP address easily). 确保获得访问者的IP地址是有效的(但请注意,任何黑客都可以轻易地伪造IP地址)。
function get_ip_address() {
// Check for shared Internet/ISP IP
if (!empty($_SERVER['HTTP_CLIENT_IP']) && validate_ip($_SERVER['HTTP_CLIENT_IP'])) {
return $_SERVER['HTTP_CLIENT_IP'];
}
// Check for IP addresses passing through proxies
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// Check if multiple IP addresses exist in var
if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') !== false) {
$iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
foreach ($iplist as $ip) {
if (validate_ip($ip))
return $ip;
}
}
else {
if (validate_ip($_SERVER['HTTP_X_FORWARDED_FOR']))
return $_SERVER['HTTP_X_FORWARDED_FOR'];
}
}
if (!empty($_SERVER['HTTP_X_FORWARDED']) && validate_ip($_SERVER['HTTP_X_FORWARDED']))
return $_SERVER['HTTP_X_FORWARDED'];
if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
return $_SERVER['HTTP_FORWARDED_FOR'];
if (!empty($_SERVER['HTTP_FORWARDED']) && validate_ip($_SERVER['HTTP_FORWARDED']))
return $_SERVER['HTTP_FORWARDED'];
// Return unreliable IP address since all else failed
return $_SERVER['REMOTE_ADDR'];
}
/**
* Ensures an IP address is both a valid IP address and does not fall within
* a private network range.
*/
function validate_ip($ip) {
if (strtolower($ip) === 'unknown')
return false;
// Generate IPv4 network address
$ip = ip2long($ip);
// If the IP address is set and not equivalent to 255.255.255.255
if ($ip !== false && $ip !== -1) {
// Make sure to get unsigned long representation of IP address
// due to discrepancies between 32 and 64 bit OSes and
// signed numbers (ints default to signed in PHP)
$ip = sprintf('%u', $ip);
// Do private network range checking
if ($ip >= 0 && $ip <= 50331647)
return false;
if ($ip >= 167772160 && $ip <= 184549375)
return false;
if ($ip >= 2130706432 && $ip <= 2147483647)
return false;
if ($ip >= 2851995648 && $ip <= 2852061183)
return false;
if ($ip >= 2886729728 && $ip <= 2887778303)
return false;
if ($ip >= 3221225984 && $ip <= 3221226239)
return false;
if ($ip >= 3232235520 && $ip <= 3232301055)
return false;
if ($ip >= 4294967040)
return false;
}
return true;
}