php 获取客户端的真实IP地址 和 检查客户端从什么地方过来的请求
/*
* 函数功能: 获取客户端的真实IP地址
*
* 为什么要用这个函数?
* 因为我们线上Web服务器绝大部分都处于Netscaler(简称NS)后面,客户端访问的地址统一由NS调度
* 由NS调度的访问其实就是NS做了一层代理, 这期间就有一个问题, 因为真实的地址是内部IP请求的
* 当我们的应用去请获取 $_SERVER["REMOTE_ADDR"] 的时候, 得到的就是 NS 的内部 IP, 获取不了
* 真正的客户端 IP 地址.
*
* 当请求经过 NS 调度之后, NS 会把客户端的真实 IP 附加到 HTTP_CLIENT_IP 后,我们要提取的就
* 是这个地址.
*
* 如测试数据:
* [HTTP_CLIENT_IP] => 192.168.2.251, 192.168.3.252, 218.82.113.110
* 这条信息是我测试的结果, 前面两个 IP 是我伪造的, 最后那个 IP 才是我真实的地址.
*
* 同样我也测试过通过代理的数据
* [HTTP_X_FORWARDED_FOR] => 192.168.2.179, 123.45.67.78 64.191.50.54
* 前面两个IP是我伪造的, 最后面那个地址才是 proxy 的真实地址
*
* 提醒:
* HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR 都可以在客户端伪造, 不要轻易直接使用这两个值, 因为
* 恶意用户可以在里面输入PHP代码, 或者像伪造 N 个", 让你的程序执行有问题, 如果要直接使用这
* 两个值的时候最简单的应该判断一下长度(最长15位), 或用正则匹配一下是否是一个有效的IP地址
*
* 参数:
*
* @param string $proxy_override, [true|false], 是否优先获取从代理过来的地址
* @return string
*
*/
function get_client_ip_from_ns($proxy_override = false)
{
if ($proxy_override) {
/* 优先从代理那获取地址或者 HTTP_CLIENT_IP 没有值 */
$ip = empty($_SERVER["HTTP_X_FORWARDED_FOR"]) ? (empty($_SERVER["HTTP_CLIENT_IP"]) ? NULL : $_SERVER["HTTP_CLIENT_IP"]) : $_SERVER["HTTP_X_FORWARDED_FOR"];
} else {
/* 取 HTTP_CLIENT_IP, 虽然这个值可以被伪造, 但被伪造之后 NS 会把客户端真实的 IP 附加在后面 */
$ip = empty($_SERVER["HTTP_CLIENT_IP"]) ? NULL : $_SERVER["HTTP_CLIENT_IP"];
}
if (empty($ip)) {
$ip = $_SERVER["REMOTE_ADDR"];
}
/* 真实的IP在以逗号分隔的最后一个, 当然如果没用代理, 没伪造IP, 就没有逗号分离的IP */
if ($p = strrpos($ip, ",")) {
$ip = substr($ip, $p+1);
}
return trim($ip);
}
/*
* 检查客户端从什么地方过来的请求
*
* <code>
* // 严格检查此页面来源中域名必须包含 .dod.com
* if (!check_client_referer(true, ".dod.com")) {
* die("非法提交的数据");
* }
* // 松散检查来源url中必须包含.51.com
* if (!check_client_referer()) {
* die("非法提交的数据");
* }
* </code>
*
* @param bool $restrict 是否进行严格的查检, 此方式为用正则对host进行匹配
* @param string $allow 允许哪些 referer 过来请求
* @return true / false 在允许的列表内返回true
*
*/
function check_client_referer($restrict = true, $allow = ".xx5.com")
{
$referer = isset($_SERVER["HTTP_REFERER"]) ? trim($_SERVER["HTTP_REFERER"]) : null;
if (empty($referer)) { return true; } /* 空的 referer 直接允许 */
if ($restrict) {
/* 更加严格的查检, 此值为true时, allow 可以输入正则来匹配 */
$url = parse_url($referer);
/* host 为空时直接返回不false */
if (empty($url["host"])) { return false; }
/* 将正则中的.替换掉为.真正匹配.再进行匹配 */
$allow = "/".str_replace(".", ".", $allow)."/";
return 0 < preg_match($allow, $url["host"]);
}
return false !== strpos($referer, $allow);
}
?>
声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
- 上一篇: 配置php.ini文件,关闭错误提示,打开错误日志,设置错误日志路径
- 下一篇: php获取手机型号
