书接上回,我们在主题中对接腾讯LBS IP查询服务后,会有一个bug:如果某篇文章评论过多,则某些评论IP定位数据无法显示,这个是因为腾讯LBS服务个人开发者的并发量限制为5次/秒。在上一个教程发布后,也有大佬发现了这个问题,不过这个问题我顺手就解决了,但是解决方案没有分享出来,因为需要改typecho系统的代码。这个已经脱离技术小白的范围,请合理折腾,折腾前记得备份数据。
原理
这一次折腾的原理是,我们在数据库中添加一个字段作为IP属地信息的一个冗余信息;当用户评论时,获取用户IP地址,调用腾讯LBS服务进行查询,将查询到的数据写入数据库中,这样就避免并发量超出限制。
执行sql语句
23.06.10:根据Typecho数据库设计文档又更新了一下sql语句
ALTER TABLE `typecho_comments`
ADD COLUMN `ipRegion` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'IP中文地址' AFTER `parent`,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`coid`) USING BTREE;
上面sql就是在字段coid后增加一个ipRegion的字段,并且添加一个备注信息。
修改代码
我们打开网站根目录,路径:/var/Widget/Base/Comments.php
这个文件是系统评论对外提供的方法,包括插入数据和查询数据等方法,有能力的同学,可以翻翻代码,基本上面都有注释;
大概55行,也就是增加评论 的方法首行,增加以下代码,将key和sign_key修改为自己申请的就可以。
$ipRegion = '';
$cip = empty($comment['ip']) ? $this->request->getIp() : $comment['ip'];
$key = '配置自己申请的key';
//签名校验的KEY
$sign_key = '配置自己申请的sign_key';
$sign = md5('/ws/location/v1/ip?ip='.$cip.'&key='.$key.$sign_key);
$url = 'https://apis.map.qq.com/ws/location/v1/ip?ip='.$cip.'&key='.$key.'&sig='.$sign;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36');
$content = curl_exec($ch);
curl_close($ch);
if($content) {
$json = json_decode($content,true);
if($json['status'] == 0 ){
$resjson = $json['result']['ad_info'];
if($resjson['nation'] == '中国'){
if($resjson['province']=='北京市'||$resjson['province']=='天津市'||$resjson['province']=='上海市'||$resjson['province']=='重庆市'){
$ipRegion = $resjson['city'];
}else{
$ipRegion = $resjson['province'].$resjson['city'];
}
}else{
$ipRegion = $resjson['nation'].$resjson['province'].$resjson['city'].$resjson['district'];
}
}
}
上面代码增加完后,大概在108行,也就是构建插入结构 那行注释里面增加一个参数,把下面代码放在[]中,
'ipRegion' => $ipRegion,
在381行后,插入下面,这个就是把查询对象增加一个输出值
'table.comments.ipRegion'
基本上请求和写入已经完成,我们再改一下后台管理界面,把这个ip属地也添加到页面上,这样后台也方便查询
打开admin/manage-comments.php
136行后增加以下代码
<br /><span><?php $comments->ipRegion(); ?>
最后我们再来修改主题的评论,这里以Joe主题为例
文件路径joe/public/comment.php
<?php $comments->ipRegion(); ?>
找到合适位置显示IP属地,我是放在112行的
<div class="agent">
<?php $comments->ipRegion(); ?> <?php _getAgentOS($comments->agent); ?> · <?php _getAgentBrowser($comments->agent); ?>
</div>
最终效果如下
看看归属地~~
现在都开始要求做这个了。
对于评论展现信息,我曾接到过很多(反应暴露评论者信息,邮箱、IP位置等等,后来我清掉了评论数据表禁止评论, 再后2023年几月 我不记得了 为响应各位,重写评论 对外部(游客)隐藏私密信息)现在在考虑要不要把评论者域名地址放出来,还在找稳妥的办法,为什么这么说呢 之前我就遇到过 通过评论注入SQL获取数据 都是高手啊 所以稳妥了之后再放出来 上面的种种都是我个人经历 还得多学学大佬们
来了来了 时隔一年 终于更新了 哈哈
主要是忙忘了
真不错
typecho 因你而精彩