Sakurairo主题提供了一个有趣的小功能,就是显示评论者的IP地址~(这个功能的介绍可以戳这个文档)
但是这就尴尬了,这个功能就没成功展示过("▔□▔)/全部都显示的是“来自: Reserved Address”
翻了一下文档,文档里面是这么写的:
显示
Reserved Address
,表示获取到的用户地址是一个私有地址。如果启用了反向代理,你需要进行额外的操作才能获取到用户的真实IP地址,请查阅其他资料以获得支持。
Σ(゚д゚;)我确实使用了反向代理啊!老习惯了,毕竟这样可以用ngnix管理流量,让同一个域名下挂不同服务,还能解析套娃(什么自己造的奇怪名词)
( ̄□ ̄||)这就难办了,得想办法解决这个问题。既然文档已经提示了这个问题,我估摸着用这个主题的好朋友们应该主要是挂网页博客,也就不需要做流量转发之类的操作,这些可能也没处理。所以打算自己翻翻代码看看能不能找到什么解决办法,说不定还能提一个PR嘿嘿(=・ω・=)
Sakurairo主题中是如何获取评论IP的
这个问题很重要,Sakurairo主题中是如何获取评论IP的呢?先不管这个问题,直接去读代码,大概会读到functions.php
里面的这段代码(啊,源代码注释就是这样的哦):
// 显示访客当前 IP
function get_the_user_ip()
{
// if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
// //check ip from share internet
// $ip = $_SERVER['HTTP_CLIENT_IP'];
// } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// //to check ip is pass from proxy
// $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
// } else {
// $ip = $_SERVER['REMOTE_ADDR'];
// }
// 简略版
// $ip = $_SERVER['HTTP_CLIENT_IP'] ?: ($_SERVER['HTTP_X_FORWARDED_FOR'] ?: $_SERVER['REMOTE_ADDR']);
$ip = $_SERVER['HTTP_CLIENT_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];
return apply_filters('wpb_get_ip', $ip);
}
( σ'ω')σ某个笨蛋橘子先入为主的认为,这段代码就是获取用户IP的嘛(毕竟注释就是这么写的),那肯定评论IP肯定也用的这个了!但其实不是,这个函数应该是处理其他内容的(我猜,可能是挂在页面某个位置显示访问者的ip什么的)〒▽〒
真正的处理评论者IP的是IpLocation.php
文件里面的下面这个函数:
/**
* 通过评论ID获取IP地理位置信息,当数据库里不存在IP地理位置信息时会自动请求接口获取
*
* @param int $comment_id 评论ID
* @return string 成功时返回IP地理位置信息:“国家 地区(省份) 城市”;失败时返回“Unknown”或“Reserved Address”或“Empty Address”
*/
public static function getIpLocationByCommentId(int $commentId)
{
$ipLocation = get_comment_meta($commentId, 'iro_ip_location', true);
if ($ipLocation) {
$location = new IpLocationParse($ipLocation);
return $location->getLocationConcision();
} else {
// 解析IP地址地理位置
$commentIp = get_comment_author_IP($commentId);
if (!empty($commentIp)) {
if (IPLocation::checkIpValid($commentIp)) {
$ipLocation = new IPLocation($commentIp);
$location = $ipLocation->getLocation();
// 记录IP地理位置信息
if ($location) {
if (iro_opt('save_location')) add_comment_meta($commentId, 'iro_ip_location', $location);
$locationParse = new IpLocationParse($location);
return $locationParse->getLocationConcision();
} else {
return __('Unknown');
}
} else {
return __('Reserved Address');
}
} else {
return __('Empty Address');
}
}
}
哎呀,看到这个'Reserved Address'
关键字那橘子可是两眼放光Σ(っ °Д °;)っ这不正是我遇到的问题吗,其中的关键,正在于这句:$commentIp = get_comment_author_IP($commentId);
这意味着,Sakurairo主题是直接从底层框架提供的API中,直接读取存储的IP信息。具体的api位于这个文件中:/wp-includes/comment.php
,其中涉及到的记录代码很容易就能搜索到,如下:
if ( ! isset( $commentdata['comment_author_IP'] ) ) {
$commentdata['comment_author_IP'] = $_SERVER['REMOTE_ADDR'];
}
修改Wordpress代码解决问题
这就是问题所在了!!!w(゚Д゚)w 他没有关心任何代理,直接读取的REMOTE_ADDR
!!!所以才会出毛病啊啊啊,由于Sakurairo主题总是从该接口获取对应的已经存储的IP地址,因此无法进一步分析用户的真实IP!!!
(つд⊂)这下好了,本以为可以给Sakurairo项目提PR了,没想到是Wordpress本身的锅。(其实我之前直接忽略了这层,因为我用到的其他插件,是能正确获取挂了反向代理的IP的,所以我就首先怀疑是主题这边的问题)
给这段代码稍作修改,如下:
if ( ! isset( $commentdata['comment_author_IP'] ) ) {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip_addresses = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$client_ip = trim($ip_addresses[0]);
} else {
$client_ip = $_SERVER['REMOTE_ADDR'];
}
$commentdata['comment_author_IP'] = $client_ip;
// $commentdata['comment_author_IP'] = $_SERVER['REMOTE_ADDR'];
}
然后就成功啦!!!ヾ(≧▽≦*)o现在能正确获取到评论者的IP信息啦!
此外,某些帖子可能会给出这种解决方法,那就是在wp-config.php
中添加下面这段代码:
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip_addresses = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$client_ip = trim($ip_addresses[0]);
} else {
$client_ip = $_SERVER['REMOTE_ADDR'];
}
( _ _)ノ|但是,没用的。这是推测这是因为在 wp-config.php
中修改的 $client_ip
变量是在全局作用域中的,但它的作用域仅限于 wp-config.php
文件以及加载 wp-config.php
的过程。当 WordPress 加载完毕时,wp-config.php
中设置的变量可能已经失效或无法直接在 WordPress 的其他文件中访问,除非你显式地将它们传递给其他部分。如果一定到这么用,或许可以这样做(吉皮特老师这么说的):
// 在需要使用 $client_ip 的地方,使用 global 关键字
add_action('init', function() {
global $client_ip;
// 使用 $client_ip 进行处理
});
至此,问题解决![]~( ̄▽ ̄)~*
Comments 1 条评论
博主 橘子
发一条评论,证明成功了