【PHP】搭建自己的 Gravatar+QQ图像 镜像站

文章摘要
为解决Gravatar在大陆访问受限的问题,作者使用PHP开发了一个集成Gravatar和QQ头像的镜像站。该镜像站支持三种调用方式:明文获取、MD5加密和Base64+Token加密,其中建议使用Base64+Token以保护用户隐私。代码可在具备PHP支持的服务器上运行,作者通过加密邮箱地址访问QQ和Gravatar头像,自动判断并返回合适图片。搭建过程中曾因阿里云服务器拦截失败,后更换香港服务器成功实现。测试页面提供了三种方式的实时演示,并建议替换域名、设置白名单以提高安全性和适配性。
— 文章部分摘要由DeepSeek深度思考而成

前言:

 – 之前使用 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图像 镜像站|不死鸟资源网
图片[2]|【PHP】搭建自己的 Gravatar+QQ图像 镜像站|不死鸟资源网
图片[3]|【PHP】搭建自己的 Gravatar+QQ图像 镜像站|不死鸟资源网

代码:

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替换为自己域名就行啦

本站资源均为作者提供和网友推荐收集整理而来,仅供学习和研究使用,请在下载后24小时内删除,谢谢合作!
【PHP】搭建自己的 Gravatar+QQ图像 镜像站|不死鸟资源网
【PHP】搭建自己的 Gravatar+QQ图像 镜像站
此内容为付费资源,请付费后查看
¥0.5
限时特惠
¥99
文章采用CC BY-NC-SA 4.0许可协议授权
付费资源
THE END
点赞14 分享