本站也是用的国产typecho开发,简单好用,但是对于技术开发人员想去修改里面的一些东西还是比较麻烦,因为不是所有人都懂PHP代码的,顶多在设计页面的时候根据自己的想法,有些改动的问题确实还是需要自己琢磨,搞不懂的地方上网搜一下,但是很多时候网上回答的那些东西不是陈年老旧就是误人子弟,大部分做了无用功,花了时间和经历都没打到想要的效果。
下面原文写的代码运行起来是可以的,但是图片量一多,回导致请求数据缓慢,阻塞页面的加载导致页面的渲染变慢,在做测试的时候我是用的本地测试很快的,没经过线上跑后面才发现这个问题,其中每个页面的渲染时间平均都超过8秒的时间,是因为本站的侧边栏有8张评论者的头像获取,平均下来一个头像就需要 1 秒的时间等待,找到问题之后去掉之前的获取代码,在网上翻找了一圈之后发现很多人也都在说这个问题,后面才翻到一个博主说的解决办法,使用 cravatar 代理支持,可以支持 Typecho 处理头像,引用官网的一句话。
Cravatar 完美兼容所有 Gravatar 头像 API 接口,同时如果你未在 Cravatar 设置头像,则会先尝试调用 Gravatar 上的头像数据,其后是 QQ 头像,最后会返回我们为你准备的一组默认头像
看明白这句话就知道该怎么做了,去掉之前的获取头像加密的方式,改成以下代码。其实下面评论有兄弟指出来问题了,我以为这是头像的地址问题,差不多,没想到两者对页面的访问速度相差十万八千里,这算是一次优化吧。
$qqMail = '1174225038@qq.com';
// $geturl = 'http://ptlogin2.qq.com/getface?&imgtype=1&uin=' . $qqMail;
// $qquser = file_get_contents($geturl);
// $str1 = explode('&k=', $qquser);
// $str2 = explode('&s=', $str1[1]);
// echo 'https://thirdqq.qlogo.cn/g?b=qq&k=' . $str2[0] . '&s=100';
// 使用 md5 处理以下,再拼接到 https://cravatar.cn/avatar/ 网址即可
$hash = md5($qqMail);
echo 'https://cravatar.cn/avatar/' . $hash;
测试以下线上访问速度,也还是很快的。
需要加密原因
这次碰到问题是在用户评论的时候会把自己邮箱绑定,这样也便于本人回复的时候可以及时做邮件通知,第二个,也是为了通过邮箱的形式拿到用户的头像,大家都知道 typecho 默认的头像访问是需要梯子的,不然会访问不上导致加载速度的变慢。所以在默认的情况下我拿到用的邮箱时,做了一个拼接或是 QQ 或者其他,国内的话就用 CDN 加速,如果是 QQ 的话就直接取得头像。如果不是 QQ 的还好,不会涉及到号码的暴露,就是说在动技术的人面前,前端的静态页面直接是可以在控制台查看的,找到头像的地方,查看图片的路径就可以看到用的 QQ 号码了,这样会被有心思的人拿做他图。所以为了避免这样的情况,只需在拿到 QQ 的加密 k 值就好,然后再拼接一起。
加密处理思路
上面也说到直接拿到头像地址拼接(如下),其中 nk
是用户的 QQ 邮箱跟着后面的 s
则是头像大小,具体可以设置100,160,640 三种可选,一般为了减少请求大小可以选 100 大小即可。
https://thirdqq.qlogo.cn/g?b=qq&nk=1174225038&s=100
这个方式是最初的那头像的方式,正如大家所看到的,如果那这个链接放在页面上,链接上的 QQ 显而易见。下面换一个方式,可以看一下如下地址。
注意:下面的值得是 k 而不是上面的 nk
https://thirdqq.qlogo.cn/g?b=qq&k=6juKG2qAgkyUF0p8sJMR5Q&s=100
可以看到地址上把 QQ 邮箱做了一个加密,用户不管怎么操作不能做到反解密的,这样有效的避免了号码暴露的问题。那我是怎么做到加密可以被官方识别的呢?其实很简单,只需在拿到号码之后,通过号码获取解密需要的 k
即可,用到的链接如下。
http://ptlogin2.qq.com/getface?&imgtype=1&uin=1174225038
可以看到我把 QQ 是用过后面拼接到 uin
的字段上了,拿到这个地址之后返回的是一个带有加密的字符 k
值,再通过截取字符,拿到加密值,最后在拼到如上第二个地址上,得到完整的链接就可以放在页面上了。看下面如何实现
获取邮箱号码加密字段
在 PHP 中有两种获取数据的方式(本人不是开发,只是找到的结果)。
- 使用 file_get_contents() 函数获取数据
- 使用 curl
两种方式各有优劣,但都可以获取。
使用 file_get_contents()
从文档找了一下这个函数的定义,file_get_contents() 把整个文件读入一个字符串中。
该函数是用于把文件的内容读入到一个字符串中的首选方法。如果服务器操作系统支持,还会使用内存映射技术来增强性能。
使用:file_get_contents(path, include_path, context, start, max_length);
我们只需要第一个参数。
$qqMail = '1174225038';
$geturl = 'http://ptlogin2.qq.com/getface?&imgtype=1&uin=' . $qqMail;
$qquser = file_get_contents($geturl);
$str1 = explode('&k=', $qquser);
$str2 = explode('&s=', $str1[1]);
echo 'https://thirdqq.qlogo.cn/g?b=qq&k=' . $str2[0] . '&s=100';
使用 curl
相比 file_get_contents()
的简单,用 curl
就要复杂一点了,可以先封装一个函数处理,然后再调用。
function _curl($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 3000);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 3000);
if (strpos($url, 'https') !== false) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
}
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36');
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
// 下面的代码和使用 file_get_contents() 那段基本一致
function _getAvatarByMail($mail)
{
// 这里是自己在模板管理做了一个 cdn 配置,如果不是qq邮箱就可以使用其他的方式加载邮箱的头像
$gravatarsUrl = Helper::options()->CustomAvatarSource ? Helper::options()->CustomAvatarSource : 'https://gravatar.ihuan.me/avatar/';
$mailLower = strtolower($mail);
$md5MailLower = md5($mailLower);
$qqMail = str_replace('@qq.com', '', $mailLower);
if (strstr($mailLower, "qq.com") && is_numeric($qqMail) && strlen($qqMail) < 11 && strlen($qqMail) > 4) {
$geturl = 'http://ptlogin2.qq.com/getface?&imgtype=1&uin=' . $qqMail;
$qquser = _curl($geturl);
$str1 = explode('&k=', $qquser);
$str2 = explode('&s=', $str1[1]);
$k = $str2[0];
echo 'https://thirdqq.qlogo.cn/g?b=qq&k=' . $k . '&s=100';
} else {
echo $gravatarsUrl . $md5MailLower . '?d=mm';
}
}
把这段代码可以放到处理邮箱的地方,返回的链接数据根据自己的博客内容做填入。