QQ空间的“神奇”图片
昨天女友說(shuō)遇到了一個(gè)奇怪的問(wèn)題,就是在別人的QQ空間的轉(zhuǎn)載上看到了自己的名字,頭像,問(wèn)我是怎么回事。晚飯后,閑來(lái)無(wú)事,想到那個(gè)問(wèn)題,就讓女友打開(kāi)那個(gè)看到自己頭像,名字的網(wǎng)頁(yè)(因?yàn)楸救藥缀醪簧峡臻g,所以空間這方面近乎白癡)。看到她說(shuō)的那個(gè)地方是一張圖片,使用chrome審查元素發(fā)現(xiàn)這張圖片來(lái)源于一個(gè)PHP文件,而且這個(gè)文件不是QQ空間自帶的:
http://qq.sennvwu.com/qzone/do.php
試圖獲取一下,無(wú)功而返。因?yàn)镻HP的運(yùn)行都是在服務(wù)器端運(yùn)行的,而用戶(hù)看到的網(wǎng)頁(yè)則是PHP的運(yùn)行結(jié)果,可以說(shuō)跟源文件沒(méi)有一毛錢(qián)關(guān)系,這就很難辦了!
想了一下,應(yīng)該是這樣一個(gè)流程:用戶(hù)查看這個(gè)文章(初始是一張圖片,no.png)——用戶(hù)點(diǎn)擊后文章內(nèi)調(diào)用定的PHP文件——PHP文件獲取當(dāng)前頁(yè)面的QQ號(hào)碼——然后通過(guò)騰訊的開(kāi)放接口查詢(xún)用戶(hù)的名字,頭像并使用其他開(kāi)放接口獲取查看文章用戶(hù)的ISP——將獲取的頭像,名字,ISP等信息加上一段話(huà)生成一張圖片——將這張圖片返回到用戶(hù)查看界面——用戶(hù)看到神奇的圖片。
在網(wǎng)上找了一些資料(畢竟對(duì)PHP了解的只是皮毛),發(fā)現(xiàn)有大神已經(jīng)全部搞定,還附帶了源碼,故轉(zhuǎn)載至此!
以下是轉(zhuǎn)載文章內(nèi)容:
昨晚上偶然看到個(gè)比較坑爹的日志,正文有一張圖片,在好友動(dòng)態(tài)列表查看的時(shí)候可以顯示自己(不是發(fā)日志的好友,是你自己)的頭像和QQ號(hào)碼、昵稱(chēng)。正文的文字稱(chēng),這是“本年度最給力神奇魔力日志(轉(zhuǎn)載會(huì)看到你最熟悉的身影)”,并且在文章底部附加了一個(gè)發(fā)廣告的QQ號(hào)碼。
?
由于這張坑爹圖片的存在,文章轉(zhuǎn)發(fā)量短短三天內(nèi)過(guò)千。這招可比那些瘋狂加群發(fā)廣告的來(lái)的更有創(chuàng)意和殺傷力,轉(zhuǎn)載傳播圖片(包括日志當(dāng)中的廣告)的人幾乎是全網(wǎng)用戶(hù)(跟所謂病毒營(yíng)銷(xiāo)差不多了)。好奇的話(huà)可以看這篇日志最初來(lái)源:hXXp://user.qzone.qq.com/732678621/blog/1363502247
一看就知道是檢測(cè)referer的把戲。早在幾年前BBS還在流行的時(shí)候,很多人設(shè)置的簽名圖具有天氣預(yù)報(bào)、客戶(hù)端信息(瀏覽器、操作系統(tǒng)、IP所在地之類(lèi))、隨機(jī)笑話(huà)、倒計(jì)時(shí)等五花八門(mén)的功能。這都得益于服務(wù)器端腳本的圖像處理功能。而客戶(hù)端的檢測(cè)則是基于HTTP請(qǐng)求中的UserAgent和Referer等信息。
但是印象中QQ空間為了防止referer潛在的安全問(wèn)題和防止圖片被防盜鏈瞎了很大功夫,凡是發(fā)表到QQ空間的日志,正文都會(huì)把引用到的所有第三方圖片資源緩存到騰訊的云端上。所以直接在日志正文中引用的圖片,是不會(huì)提交REFER到我們的服務(wù)器腳本上的。
文中特別稱(chēng),“請(qǐng)轉(zhuǎn)載后用電腦進(jìn)入個(gè)人中心看”。為什么要特別說(shuō)明是“個(gè)人中心”呢?我刷新了好久的動(dòng)態(tài),終于看到了圖片所說(shuō)的效果。頁(yè)面生成的DOM代碼為:
imgsrc="http://qq.sennvwu.com/qzone/do.phponload="QZFL.media.reduceImage(0,400,300,{trueSrc:'http:\/\/qq.sennvwu.com\/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.parentNode;p.style.width=_w+'px';p.style.height=_h+'px';}}})"
?width="400">
?
原來(lái)QQ空間還是會(huì)顯示源地址的圖片的,僅限于在“個(gè)人中心”。這時(shí)候請(qǐng)求圖片附帶的HTTP_REFERER的值為
http://user.qzone.qq.com/QQ號(hào)/infocenter
號(hào)碼就是這樣提取到的。如果REFERER不滿(mǎn)足條件,這個(gè)php將在header中發(fā)送Location跳轉(zhuǎn)到同一目錄下的no.png。
那么后臺(tái)是如何取到QQ頭像、昵稱(chēng)等信息的呢?我Google到了一個(gè)騰訊的WebService接口:
http://base.qzone.qq.com/fcg-bin/cgi_get_portrait.fcg?uins=QQ號(hào)
不需要任何憑證信息即可獲取uins指定的QQ號(hào)碼的頭像、昵稱(chēng)信息,返回的格式為JSON。另外上面的圖片還有一個(gè)顯示地理位置和ISP的功能,這個(gè)就比較常見(jiàn)了。我找到了一個(gè)比較好用的接口,來(lái)自TB:
http://ip.taobao.com/service/getIpInfo.php?ip=127.0.0.1
格式同樣也是JSON。
接下來(lái)實(shí)現(xiàn)這個(gè)效果就比較簡(jiǎn)單了,通過(guò)REFERER檢測(cè)用戶(hù)的QQ號(hào)碼,然后在后臺(tái)下載頭像、昵稱(chēng)等信息,用GD函數(shù)繪制上圖片,返回客戶(hù)端。
我也折騰了一個(gè)‘神奇圖片“發(fā)到空間,居然捉弄了一群人。下面是php語(yǔ)言的實(shí)現(xiàn)代碼。為了減少后端的流量,對(duì)下載的頭像做了緩存處理:
?
<?php
error_reporting(0);
ob_start();
header('Content-Type: p_w_picpath/png');
define('IMG_NO', "no.png"); #剛開(kāi)始顯示的提示信息
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); #緩存時(shí)間,單位秒
#(!is_dir(CACHE_PATH) && is_writable(CACHE_PATH)) || die;
/*
$remote: 遠(yuǎn)程URL
$local: 本地緩存路徑
$expire: 過(guò)期時(shí)間。為-1時(shí),永久不更新緩存
*/
function load_from_cache($remote, $local, $expire = CACHE_EXPIRE, $as_path = false) {
#過(guò)濾潛在的危險(xiǎn)字符
$local = preg_replace("/[.\/\\\?\*\'\"\|\:\<\>]/", "_", $local);
$cache = CACHE_PATH.$local;
#查找緩存
if(file_exists($cache) && ($expire = -1 || filemtime($cache) - time() < $expire))
return $as_path ? $cache : file_get_contents($cache);
#文件不存在或緩存過(guò)期,重新下載
$content = file_get_contents($remote);
file_put_contents($cache, $content);
return $as_path ? $cache : $content;
}
/*
返回客戶(hù)端信息。
*/
function client_info() {
$url = "http://ip.taobao.com/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.qzone.qq.com/123456789/infocenter";
$pattern = "/http:\/\/user.qzone.qq.com\/(\d+)\/infocenter/";
if(preg_match($pattern, $referer, $matches)) {
#獲取QQ號(hào)碼
$uin = $matches[1];
$info = explode('"', load_from_cache(
"http://base.qzone.qq.com/fcg-bin/cgi_get_portrait.fcg?uins=".$uin, $uin));
$avatar = $info[3];
$nickname = iconv("GBK", "UTF-8//IGNORE", $info[5]);
$client = client_info();
#重點(diǎn)來(lái)了,生成圖片
try{
$im = p_w_picpathcreatefrompng(IMG_BACKGROUND);
? ?#繪制頭像
? ?$avatar_file = load_from_cache($avatar, $uin.".jpg", 60*60*24, true);
? ?$im_avatar = p_w_picpathcreatefromjpeg($avatar_file);
p_w_picpathcopymerge($im, $im_avatar, 14, 14, 0, 0, 100, 100, 100);
p_w_picpathdestroy($im_avatar);
#繪制文字
$blue = p_w_picpathcolorallocate($im, 0, 0x99, 0xFF);
$white = p_w_picpathcolorallocate($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) {
p_w_picpathttftext($im, $value[0], 0, $value[1], $value[2], $value[3], FONT_NAME,?
mb_convert_encoding($value[4], "html-entities", "utf-8")); #解決亂碼問(wèn)題
}
p_w_picpathpng($im);
p_w_picpathdestroy($im);
header("Content-Length: ".ob_get_length());
? ? ? ? ob_end_flush();
} catch (Exception $e) {
? ?#die($e->getMessage());
? ?$error = true;
}
} else {
$error = true;
}
if($error){
header('Content-Length: '.filesize(IMG_NO));
? ? echo file_get_contents(IMG_NO);
}
?
?
?
?
?
轉(zhuǎn)載于:https://blog.51cto.com/hero2012/1167795
總結(jié)
以上是生活随笔為你收集整理的QQ空间的“神奇”图片的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Microsoft和AWS推出免费的云优
- 下一篇: Firefox 扩展开发 install