前言:
– 之前使用 cn 的 Gravatar 老是被墙无法显示,使用 gemini 写了一个简单页面自己搭建一个;
– 搭建要求有一个可以正常访问 Gravatar 原站的虚拟主机或是服务器;
– 支持 PHP 的虚拟主机即可运行代码;
介绍:
1. 集成了 Gravatar+QQ 头像,默认优先获取 QQ 头像
2. 支持三种方法调用:
– 明文获取 (QQ 邮箱可以仅输入数字)
– md5 方式(仅支持 Gravatar,使用 QQ 邮箱获取的也是 Gravatar)
– base64+token(同时支持 Gravatar+QQ 头像,使用 QQ 邮箱优先获取 QQ 头像)
注:建议使用 base64+token 方式调用,减少用户隐私泄露
测试预览页面:
https://img.ximi.me/avatar/test/
![图片[1]|【PHP】搭建自己的 Gravatar+QQ图像 镜像站|不死鸟资源网](https://busi.net/wp-content/uploads/2025/06/20250608194824448-image.png)
![图片[2]|【PHP】搭建自己的 Gravatar+QQ图像 镜像站|不死鸟资源网](https://busi.net/wp-content/uploads/2025/06/20250608194828557-image.png)
![图片[3]|【PHP】搭建自己的 Gravatar+QQ图像 镜像站|不死鸟资源网](https://busi.net/wp-content/uploads/2025/06/20250608194831258-image.png)
代码:
1.index.php
/avatar/index.php
<?php
//=========== emal地址加密解密 ================
$secret_key = 'test123456';
function xor_encrypt_email($email, $key) {
$encrypted_email = '';
$key_length = strlen($key);
for ($i = 0; $i < strlen($email); $i++) {
$encrypted_email .= chr(ord($email[$i]) ^ ord($key[$i % $key_length]));
}
return base64_encode($encrypted_email); // 通常会用 Base64 编码结果,使其更易于传输
}
function xor_decrypt_email($encrypted_base64, $key) {
if (base64_encode(base64_decode($encrypted_base64, true)) === $encrypted_base64) {
$encrypted_email = base64_decode($encrypted_base64);
$decrypted_email = '';
$key_length = strlen($key);
for ($i = 0; $i < strlen($encrypted_email); $i++) {
$decrypted_email .= chr(ord($encrypted_email[$i]) ^ ord($key[$i % $key_length]));
}
return $decrypted_email;
} else {
return null; // 解密失败返回 null
}
}
//=========== emal地址加密解密 end ================
// 函数用于判断字符串是否看起来像一个邮箱地址
function is_valid_email($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
// 检查是否有 hash 参数
if (isset($_GET['hash'])) {
$hash = $_GET['hash'];
$size = isset($_GET['s']) && is_numeric($_GET['s']) ? intval($_GET['s']) : 100; // s 参数不存在默认为 100
$avatar_url = ''; // 初始化头像 URL
$qq_size = 100; // QQ 头像固定大小
$normalized_hash = mb_convert_kana(trim(strval($hash)), 'n', 'UTF-8');
// 如果 hash 是纯数字,则直接作为 QQ 号码处理,不进行解密
if (preg_match('/^[0-9]+$/', $normalized_hash)) {
$avatar_url = "https://q1.qlogo.cn/g?b=qq&nk=" . strval($normalized_hash) . "&s={$qq_size}";
} else {
// 尝试解密 hash
$decrypted_email = xor_decrypt_email($hash, $secret_key);
if ($decrypted_email !== null) {
$normalized_decrypted_email = mb_convert_kana(trim(strval($decrypted_email)), 'n', 'UTF-8');
// 如果解密后是有效的 @qq.com 邮箱地址,则构建 QQ 头像 URL
if (is_valid_email($normalized_decrypted_email) && strtolower(substr($normalized_decrypted_email, -7)) === '@qq.com') {
$qq_number = str_replace('@qq.com', '', $normalized_decrypted_email);
$avatar_url = "https://q1.qlogo.cn/g?b=qq&nk=" . strval($qq_number) . "&s={$qq_size}";
} else {
// 解密成功但不是 QQ 邮箱,尝试作为邮箱进行 Gravatar 哈希
if (is_valid_email($normalized_decrypted_email)) {
$avatar_url = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($normalized_decrypted_email))) . "?s={$size}";
} else {
$avatar_url = "https://www.gravatar.com/avatar/{$hash}?s={$size}"; // 解密失败且不是邮箱,直接使用原始 hash
}
}
} else {
// 解密失败,尝试将原始 hash 作为 QQ 邮箱或普通邮箱处理
if (is_valid_email($normalized_hash) && strtolower(substr($normalized_hash, -7)) === '@qq.com') {
$qq_number = str_replace('@qq.com', '', $normalized_hash);
$avatar_url = "https://q1.qlogo.cn/g?b=qq&nk=" . strval($qq_number) . "&s={$qq_size}";
} elseif (is_valid_email($normalized_hash)) {
$avatar_url = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($normalized_hash))) . "?s={$size}";
} else {
$avatar_url = "https://www.gravatar.com/avatar/{$hash}?s={$size}"; // 解密失败且不是邮箱
}
}
}
// 获取头像并输出
if (!empty($avatar_url)) {
$headers = @get_headers($avatar_url);
if ($headers && strpos($headers[0], '200 OK') !== false) {
$mime_type = '';
foreach ($headers as $header) {
if (stripos($header, 'Content-Type:') === 0) {
$mime_type = trim(substr($header, strlen('Content-Type:')));
break;
}
}
if ($mime_type) {
header("Content-Type: " . $mime_type);
}
readfile($avatar_url);
exit; // 确保脚本在输出图片后停止执行
} else {
http_response_code(404); // 设置 404 Not Found 状态码
echo "头像未找到。";
exit;
}
} else {
http_response_code(404); // 设置 404 Not Found 状态码
echo "头像 URL 构建失败。";
exit;
}
} else {
// 如果缺少 hash 参数
http_response_code(400); // 设置 400 Bad Request 状态码
echo "请求无效:请提供有效的 hash 参数。";
}
?>
2. 此文件仅测试时使用,可删除
/avatar/text/index.php
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gravatar+QQ图像显示测试 (PHP 实现)</title>
<style>
.module {
border: 1px solid #ccc;
padding: 20px;
margin-bottom: 20px;
}
.input-group {
margin-bottom: 10px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"], input[type="email"] {
width: 100%;
padding: 8px;
margin-bottom: 10px;
box-sizing: border-box;
}
button {
padding: 10px 15px;
cursor: pointer;
}
img {
max-width: 100%;
height: auto;
margin-top: 10px;
border: 1px solid #eee;
}
.hidden-img {
display: none;
}
</style>
</head>
<body onload="restoreScrollPosition()">
<h1>Gravatar+QQ图像显示测试</h1>
<div class="module">
<h2>1. 明文方式显示图像 (通过 img.ximi.me/avatar/)</h2>
<form method="GET" onsubmit="saveScrollPosition()">
<div class="input-group">
<label for="plain-email">邮箱地址:</label>
<input type="email" id="plain-email" name="plain_email" placeholder="输入邮箱地址" value="<?php echo isset($_GET['plain_email']) ? htmlspecialchars($_GET['plain_email']) : ''; ?>">
</div>
<div class="input-group">
<label for="plain-url">生成图片地址:</label>
<input type="text" id="plain-url" readonly placeholder="图片地址将在此显示" value="<?php if (isset($_GET['plain_email'])) echo 'https://img.ximi.me/avatar/?hash=' . urlencode($_GET['plain_email']) . '&s=100'; ?>">
</div>
<button type="submit">生成预览</button>
</form>
<img id="plain-avatar" class="<?php if (!isset($_GET['plain_email'])) echo 'hidden-img'; ?>" src="<?php if (isset($_GET['plain_email'])) echo 'https://img.ximi.me/avatar/?hash=' . urlencode($_GET['plain_email']) . '&s=100'; ?>" alt="明文头像预览">
<p style="font-size: 0.8em; color: #777;">注意:此方法QQ邮箱默认优先获取QQ头像,其它邮箱则是gravatar图像。</p>
</div>
<div class="module">
<h2>2. MD5 方式显示图像 (通过 img.ximi.me/avatar/)</h2>
<form method="GET" onsubmit="saveScrollPosition()">
<div class="input-group">
<label for="md5-email">邮箱地址:</label>
<input type="email" id="md5-email" name="md5_email" placeholder="输入邮箱地址" value="<?php echo isset($_GET['md5_email']) ? htmlspecialchars($_GET['md5_email']) : ''; ?>">
</div>
<div class="input-group">
<label for="md5-url">生成图片地址:</label>
<input type="text" id="md5-url" readonly placeholder="图片地址将在此显示" value="<?php if (isset($_GET['md5_email'])) echo 'https://img.ximi.me/avatar/?hash=' . md5(strtolower($_GET['md5_email'])) . '&s=100'; ?>">
</div>
<button type="submit">生成预览</button>
</form>
<img id="md5-avatar" class="<?php if (!isset($_GET['md5_email'])) echo 'hidden-img'; ?>" src="<?php if (isset($_GET['md5_email'])) echo 'https://img.ximi.me/avatar/?hash=' . md5(strtolower($_GET['md5_email'])) . '&s=100'; ?>" alt="MD5 头像预览">
<p style="font-size: 0.8em; color: #777;">注意:此方法默认仅gravatar图像可用,输入QQ邮箱获取到的也是gravatar平台图像。</p>
</div>
<div class="module">
<h2>3. Base64 + Token 方式显示图像 (通过 img.ximi.me/avatar/)</h2>
<form method="GET" onsubmit="saveScrollPosition()">
<div class="input-group">
<label for="base64-email">邮箱地址:</label>
<input type="email" id="base64-email" name="base64_email" placeholder="输入邮箱地址" value="<?php echo isset($_GET['base64_email']) ? htmlspecialchars($_GET['base64_email']) : ''; ?>">
</div>
<div class="input-group">
<label for="base64-url">生成图片地址:</label>
<input type="text" id="base64-url" readonly placeholder="图片地址将在此显示" value="<?php
if (isset($_GET['base64_email'])) {
$secretKey = 'test123456'; // 请替换为你的实际密钥
echo 'https://img.ximi.me/avatar/?hash=' . base64_encode(xor_encrypt_email($_GET['base64_email'], $secretKey)) . '&s=100';
}
?>">
</div>
<button type="submit">生成预览</button>
</form>
<img id="base64-avatar" class="<?php if (!isset($_GET['base64_email'])) echo 'hidden-img'; ?>" src="<?php
if (isset($_GET['base64_email'])) {
$secretKey = 'test123456'; // 请替换为你的实际密钥
echo 'https://img.ximi.me/avatar/?hash=' . base64_encode(xor_encrypt_email($_GET['base64_email'], $secretKey)) . '&s=100';
}
?>" alt="Base64 + Token 头像预览">
<p style="font-size: 0.8em; color: #777;">注意:此方法QQ邮箱默认优先获取QQ头像,其它邮箱则是gravatar图像。</p>
<p style="font-size: 0.8em; color: #777;padding-left:3em;">Base64 编码后的结果作为 hash 传递给 img.ximi.me/avatar/,你的后端 PHP 脚本需要能够正确处理并解密。</p>
</div>
<?php
// 你的 xor_encrypt_email 函数定义 (确保只定义一次)
function xor_encrypt_email($email, $key) {
$encrypted_email = '';
$key_length = strlen($key);
for ($i = 0; $i < strlen($email); $i++) {
$encrypted_email .= chr(ord($email[$i]) ^ ord($key[$i % $key_length]));
}
return $encrypted_email;
}
?>
<script>
function saveScrollPosition() {
sessionStorage.setItem('scrollPosition', window.scrollY);
}
function restoreScrollPosition() {
const scrollPosition = sessionStorage.getItem('scrollPosition');
if (scrollPosition !== null) {
window.scrollTo(0, parseInt(scrollPosition));
sessionStorage.removeItem('scrollPosition'); // 清除存储的位置
}
// 显示图片 (如果 URL 参数存在)
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('plain_email')) {
document.getElementById('plain-avatar').classList.remove('hidden-img');
}
if (urlParams.get('md5_email')) {
document.getElementById('md5-avatar').classList.remove('hidden-img');
}
if (urlParams.get('base64_email')) {
document.getElementById('base64-avatar').classList.remove('hidden-img');
}
}
</script>
</body>
</html>
原文:
【PHP】搭建自己的 Gravatar+QQ 图像 镜像站
https://www.ximi.me/post-6032.html
成功搭建代理,不推荐使用阿里云服务器国内,我搭建半天不成功,发现被拦截,换了一台香港服务器正常使用。代码也有点问题,测试页面的网址使用的是绝对地址,每次展示的都是你的网址,我给修改了。
演示地址: https://note.jeffer.xyz/avatar/test/
评论区:https://www.jeffer.xyz/cid/2786.html
建议添加白名单域名,锁定使用域名,其他域名一律拒接。
测试页面本就是调试使用的,后期直接删除就好;
修改也简单:记事本打开直接搜索img.ximi.me替换为自己域名就行啦