修改DouPHP代码及数据库以支持适配IPv6显示

在登录DouPHP后台时,发现管理员登录记录IP地址总显示127.0.0.1,以为是使用了WAF导致,在修改CDN回源绕过WAF后仍然如此。通过查看代码后发现DouPHP对获取到的IP地址只要不符合IPv4的正则表达式就返回127.0.0.1。IPv6已经成为网络通信的主流标准,官方至今(DouPHP版本v1.8 Release 20250217)仍未进行适配,为了正确显示IPv6,需要自行修改以适配。

在include/common.class.php修改 get_ip() 方法以修正正则表达式:确保正则表达式能够匹配完整的 IPv6 地址,修改后代码如下。

function get_ip() {
    static $ip;
    if (isset($_SERVER)) {
        if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
            // 处理 HTTP_X_FORWARDED_FOR 中可能包含的多个 IP 地址
            $ip_list = explode(',', $_SERVER["HTTP_X_FORWARDED_FOR"]);
            $ip = trim($ip_list[0]); // 取第一个 IP 地址
        } else if (isset($_SERVER["HTTP_CLIENT_IP"])) {
            $ip = $_SERVER["HTTP_CLIENT_IP"];
        } else {
            $ip = $_SERVER["REMOTE_ADDR"];
        }
    } else {
        if (getenv("HTTP_X_FORWARDED_FOR")) {
            $ip_list = explode(',', getenv("HTTP_X_FORWARDED_FOR"));
            $ip = trim($ip_list[0]); // 取第一个 IP 地址
        } else if (getenv("HTTP_CLIENT_IP")) {
            $ip = getenv("HTTP_CLIENT_IP");
        } else {
            $ip = getenv("REMOTE_ADDR");
        }
    }

    // 支持 IPv4 和 IPv6 的正则表达式
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
        return $ip;
    } else {
        return '127.0.0.1'; // 默认返回本地回环地址
    }
}

数据库中IP字段的类型为 VARCHAR(15),这是 IPv4 的长度限制,需要将其调整为支持 IPv6 的长度。IPv6 地址最长为 39 个字符,因此将字段长度设置为 VARCHAR(39) 或更高。可手动修改或执行以下sql语句:

-- 管理员登录记录中的IP
ALTER TABLE `dou_admin_log` MODIFY COLUMN `ip` VARCHAR(40);
-- 插件智能客服对话记录中的首次访问IP和最近访问IP
ALTER TABLE `dou_chat_service` MODIFY COLUMN `first_ip` VARCHAR(40);
ALTER TABLE `dou_chat_service` MODIFY COLUMN `last_ip` VARCHAR(40);
-- 插件智能客服对话记录的每条对话记录IP(虽然后台没有显示,但在数据库中有该字段)
ALTER TABLE `dou_chat_service_recorde` MODIFY COLUMN `ip` VARCHAR(40);

如果没有安装插件智能客服,只需要修改或执行第一个sql语句。

发表回复