QQ空间中的这种头像是b站怎么弄动态头像得?

1523人阅读
导读:昨天遇到了一个奇怪的问题,就是在别人的QQ空间的转载上看到了自己的名字,头像,问我是怎么回事。晚饭后,闲来无事,想到那个问题,就打开那个看到自己头像,名字的网页(因为本人几乎不上空间,所以空间这方面近乎白痴)。看到那个地方是一张图片,使用chrome审查元素发现这张图片来源于一个PHP文件,而且这个文件不是QQ空间自带的:
/qzone/do.php
试图获取一下,无功而返。因为PHP的运行都是在服务器端运行的,而用户看到的网页则是PHP的运行结果,可以说跟源文件没有一毛钱关系,这就很难办了!
想了一下,应该是这样一个流程:用户查看这个文章(初始是一张图片,no.png)——用户点击后文章内调用定的PHP文件——PHP文件获取当前页面的QQ号码——然后通过腾讯的开放接口查询用户的名字,头像并使用其他开放接口获取查看文章用户的ISP——将获取的头像,名字,ISP等信息加上一段话生成一张图片——将这张图片返回到用户查看界面——用户看到神奇的图片。
一看就知道是检测referer的把戏。早在几年前BBS还在流行的时候,很多人设置的签名图具有天气预报、客户端信息(浏览器、操作系统、IP所在地之类)、随机笑话、倒计时等五花八门的功能。这都得益于服务器端脚本的图像处理功能。而客户端的检测则是基于HTTP请求中的UserAgent和Referer等信息。
但是印象中QQ空间为了防止referer潜在的安全问题和防止图片被防盗链瞎了很大功夫,凡是发表到QQ空间的日志,正文都会把引用到的所有第三方图片资源缓存到腾讯的云端上。所以直接在日志正文中引用的图片,是不会提交REFER到我们的服务器脚本上的。
文中特别称,“请转载后用电脑进入个人中心看”。为什么要特别说明是“个人中心”呢?我刷新了好久的动态,终于看到了图片所说的效果。页面生成的DOM代码为:
imgsrc=&/qzone/do.php
onload=&QZFL.media.reduceImage(0,400,300,{trueSrc:'http:\/\/\/qzone\/do.php',callback:function(img,type,ew,eh,o){var _h = Math.floor(o.oh/o.k),_w = Math.floor(o.ow/o.k);if(_w&=ew
&& _h&=eh){var p=img.parentNp.style.width=_w+'px';p.style.height=_h+'px';}}})&
width=&400&&
原来QQ空间还是会显示源地址的图片的,仅限于在“个人中心”。这时候请求图片附带的HTTP_REFERER的值为
http://user./QQ号/infocenter
号码就是这样提取到的。如果REFERER不满足条件,这个php将在header中发送Location跳转到同一目录下的no.png。
那么后台是如何取到QQ头像、昵称等信息的呢?我Google到了一个腾讯的WebService接口:
http://base./fcg-bin/cgi_get_portrait.fcg?uins=QQ号
不需要任何凭证信息即可获取uins指定的QQ号码的头像、昵称信息,返回的格式为JSON。另外上面的图片还有一个显示地理位置和ISP的功能,这个就比较常见了。我找到了一个比较好用的接口,来自TB:
/service/getIpInfo.php?ip=127.0.0.1
格式同样也是JSON。
接下来实现这个效果就比较简单了,通过REFERER检测用户的QQ号码,然后在后台下载头像、昵称等信息,用GD函数绘制上图片,返回客户端。
我也折腾了一个‘神奇图片“发到空间,居然捉弄了一群人。下面是php语言的实现代码。为了减少后端的流量,对下载的头像做了缓存处理:
error_reporting(0);
ob_start();
header('Content-Type: image/png');
define('IMG_NO', &no.png&); #刚开始显示的提示信息
define('IMG_BACKGROUND', &background.png&);
define('IMG_WIDTH', 400);
define('IMG_HEIGHT', 128);
define('FONT_NAME', &AdobeHeitiStd-Regular.otf&); #字体文件名
define('CACHE_PATH', rtrim(realpath(&./cache&), '/').'/'); #缓存目录
define('CACHE_EXPIRE', 60*60); #缓存时间,单位秒
#(!is_dir(CACHE_PATH) && is_writable(CACHE_PATH)) ||
$remote: 远程URL
$local: 本地缓存路径
$expire: 过期时间。为-1时,永久不更新缓存
function load_from_cache($remote, $local, $expire = CACHE_EXPIRE, $as_path = false) {
#过滤潜在的危险字符
$local = preg_replace(&/[.\/\\\?\*\'\&\|\:\&\&]/&, &_&, $local);
$cache = CACHE_PATH.$
if(file_exists($cache) && ($expire = -1 || filemtime($cache) - time() & $expire))
return $as_path ? $cache : file_get_contents($cache);
#文件不存在或缓存过期,重新下载
$content = file_get_contents($remote);
file_put_contents($cache, $content);
return $as_path ? $cache : $
返回客户端信息。
function client_info() {
$url = &/service/getIpInfo.php?ip=&;
$ip = ($_SERVER[&HTTP_VIA&] && $_SERVER[&HTTP_X_FORWARDED_FOR&] ?
$_SERVER[&HTTP_X_FORWARDED_FOR&] : $_SERVER[&REMOTE_ADDR&]);
$info = explode('&', load_from_cache($url.$ip, $ip, -1));
$string = $info[7].$info[23].$info[31].$info[47];
return json_decode('&'.$string.'&');
$referer = $_SERVER['HTTP_REFERER'];
#$referer = &http://user.//infocenter&;
$pattern = &/http:\/\/user.\/(\d+)\/infocenter/&;
if(preg_match($pattern, $referer, $matches)) {
#获取QQ号码
$uin = $matches[1];
$info = explode('&', load_from_cache(
&http://base./fcg-bin/cgi_get_portrait.fcg?uins=&.$uin, $uin));
$avatar = $info[3];
$nickname = iconv(&GBK&, &UTF-8//IGNORE&, $info[5]);
$client = client_info();
#重点来了,生成图片
$im = imagecreatefrompng(IMG_BACKGROUND);
&&& #绘制头像
&&& $avatar_file = load_from_cache($avatar, $uin.&.jpg&, 60*60*24, true);
&&& $im_avatar = imagecreatefromjpeg($avatar_file);
imagecopymerge($im, $im_avatar, 14, 14, 0, 0, 100, 100, 100);
imagedestroy($im_avatar);
$blue = imagecolorallocate($im, 0, 0x99, 0xFF);
$white = imagecolorallocate($im, 0xFF, 0xFF, 0xFF);
$texts = array(
array(12, 148, 40, $white, $uin),
array(18, 125, 70, $blue, $nickname),
array(16, 125, 100, $blue, $client)
foreach($texts as $key=&$value) {
imagettftext($im, $value[0], 0, $value[1], $value[2], $value[3], FONT_NAME,
mb_convert_encoding($value[4], &html-entities&, &utf-8&)); #解决乱码问题
imagepng($im);
imagedestroy($im);
header(&Content-Length: &.ob_get_length());
&&&&&&& ob_end_flush();
} catch (Exception $e) {
&&& #die($e-&getMessage());
&&& $error =
if($error){
header('Content-Length: '.filesize(IMG_NO));
&&& echo file_get_contents(IMG_NO);
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1595次
排名:千里之外404错误 - 设计帝国

我要回帖

更多关于 微信头像透明怎么弄 的文章

 

随机推荐