Adminer 6.1.2 配置与插件详解
Adminer 6.1.2 无传统配置文件,本篇详解其三条配置途径(常量与环境变量、CSS/主题覆盖、插件体系):Plugin 基类与钩子机制、plugins-enabled 加载流程与 plugin-loader 生成器实操,内置 51 个插件与 8 个扩展驱动分类速查,login-ip 白名单(含 ::ffff: IPv4 映射陷阱)与 dump-date 全链实测,自定义「隐藏服务器字段」插件实战,Editor 变体部署与安全加固清单。
Adminer 6.1.2 配置与插件详解
目标:掌握 Adminer 6.1.2 的全部配置途径与插件体系——单文件应用没有传统配置文件与 CLI,个性化全部通过「常量与入口组装、CSS 覆盖、插件钩子」三条途径完成;本篇逐项实操官方插件的启用与自定义插件开发,完成 IP 白名单、导出文件名、隐藏服务器字段等实测,并给出生产安全加固清单。本篇所有命令与回显均在 Ubuntu 22.04.5 LTS + Apache2 + PHP 8.1.2 FPM 环境实测通过(部署过程见《Ubuntu 22.04 安装 Adminer 6.1.2 指南》)。
一、环境信息
本篇实测环境与关键路径如下:
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- Web/PHP:Apache2 2.4.52(mpm_event + proxy_fcgi)+ PHP 8.1.2-1ubuntu2.27 FPM
- Adminer:6.1.2(官方单文件,569128 字节,站点目录 /var/www/html/adminer/)
- 自托管入口:/var/www/html/adminer/index.php(自定义 adminer_object(),见 5.2)
- 官方插件目录:/var/www/html/adminer/plugins/(从官方源码仓库 plugins/ 目录获取)
- 被管理数据库:MySQL 8.0.46(主机 mysql1,账号 root/q1w2e3r4,库 shop)与 PostgreSQL 16(主机 pg1,账号 postgres/q1w2e3r4)
- 对照形态:PHP 内置服务器(php -S)形态用于演示 REMOTE_ADDR 形态差异(见 6.1)
💡 说明:Adminer 没有 conf 文件、没有 CLI 子命令、没有数据库存储的配置——这是单文件设计的必然结果。所有「配置」分三类:入口组装与常量(改行为)、CSS 与主题(改外观)、插件(改功能)。读懂本章第三节的三条途径,就能定位任何定制需求的落点;官方发行的容器形态另提供三个环境变量(见《Adminer 6.1.2 Docker 部署指南》第六章),与本文的自托管配置途径一一对应。
二、前置条件
- 已有一个可运行的 Adminer 6.1.2(部署见《Ubuntu 22.04 安装 Adminer 6.1.2 指南》),站点目录可写:
ls -l /var/www/html/adminer/
实测回显:
-rw-r--r-- 1 root www-data 569128 Oct 19 18:44 adminer-6.1.2.php
-rw-r--r-- 1 root www-data 331 Oct 19 19:24 index.php
drwxr-xr-x 2 root www-data 4096 Oct 19 19:24 plugins
- 插件文件需要从官方源码仓库获取(plugins/ 目录,随源码包 adminer-6.1.2.zip 分发):
mkdir -p /var/www/html/adminer/plugins
curl -fsSL -o /var/www/html/adminer/plugins/dump-date.php \
https://raw.githubusercontent.com/vrana/adminer/master/plugins/dump-date.php
curl -fsSL -o /var/www/html/adminer/plugins/login-ip.php \
https://raw.githubusercontent.com/vrana/adminer/master/plugins/login-ip.php
ls -l /var/www/html/adminer/plugins/
实测回显:
-rw-r--r-- 1 root root 1348 Oct 19 19:24 dump-date.php
-rw-r--r-- 1 root root 2276 Oct 19 19:24 login-ip.php
- PHP 命令行可用(语法检查与配置核对用):
php8.1 -v | head -1
实测回显:
PHP 8.1.2-1ubuntu2.27 (cli) (built: Oct 13 2026 18:55:46) (NTS)
三、配置方式总览
Adminer 6.1.2 的配置途径全表(每条均经实测):
| 途径 | 落点 | 典型用途 | 生效方式 |
|---|---|---|---|
| 自托管入口组装 | 站点目录 index.php 的 adminer_object() | 固定服务器、装配插件 | 每次请求组装插件实例 |
| PHP 常量 | 引入 adminer.php 前定义 Adminer\SERVER 等 | 固定目标服务器 | 每次请求读取 |
| CSS 覆盖 | 站点目录 adminer.css | 品牌色、字体、布局微调 | 每次页面加载 |
| 官方主题 | 官方源码包 designs/ 28 套主题 CSS | 整体换肤 | 主题 CSS 复制为 adminer.css 覆盖层 |
| 官方插件 | plugins/ 51 个官方插件文件 | 登录安全、导出增强、编辑体验 | adminer_object() 返回插件实例 |
| 自定义插件 | 自写类文件,同一方式装配 | 隐藏字段、对接内部认证、审计 | 同上 |
💡 技术拓展:「PHP 应用的配置层级」不止 Adminer 一种做法,常见方案对比——
方案 代表 特点 配置文件(ini/yaml) phpMyAdmin config.inc.php 改完即生效,文件可版本化 环境变量 十二要素应用、Adminer 容器发行版 部署编排友好,不可存复杂结构 数据库存储配置 WordPress wp_options 运行时可改,依赖库可用 入口代码装配 Adminer 自托管(本文主线) 单文件即全部,装配逻辑一目了然 Adminer 的取舍是把复杂度收进「入口组装」一处:默认零配置即可用(直接访问 adminer-6.1.2.php),需要定制时再写一个几行的 index.php。本篇实测以自托管装配为主线。
四、核心配置项详解
4.1 服务器与默认服务器(SERVER 常量)
登录页「服务器」字段决定 Adminer 去连哪台数据库。自托管场景用 Adminer\SERVER 常量固定目标服务器(在引入 adminer.php 前定义):
<?php
// /var/www/html/adminer/fixed.php —— 固定服务器形态的入口
namespace Adminer {
const SERVER = 'mysql1'; // 固定目标服务器,登录页不再询问
}
namespace {
require 'adminer-6.1.2.php';
}
⚠️ 注意:常量方式下登录页不再出现可编辑的服务器输入框,适合「单库管理入口」;多库运维场景不要用常量固定,改为插件装配(见 6.3,可预填或隐藏)。官方容器发行版用
ADMINER_DEFAULT_SERVER环境变量实现「预填但可改」的默认效果(实测见《Adminer 6.1.2 Docker 部署指南》第六章)。
4.2 语言配置
登录页语言下拉内置 46 种语言(实测登录页 option 清单:en/cs/de/es/fr/ru/ja/zh 简体中文/zh-tw 繁體中文/ko 等),切换即提交 lang=zh 存入会话,无需配置文件。若部署对象是纯英文运维团队,可直接改用仅英文变体 adminer-6.1.2-en.php(GitHub Releases v6.1.2 附件,实查存在)从源头减小文件体积。
4.3 主题(adminer.css 覆盖与官方主题)
Adminer 的外观定制只有一个挂载点:站点目录下的 adminer.css——存在即被页面引用为覆盖样式(页面 head 自动追加引用,无需改任何代码)。官方 28 套社区主题(官方源码仓库 designs/ 目录实查 2026-10-20):adminer-border、adminer-dark、brade、bueltge、cpanel、dracula、esterka、flat、galkaev、haeckel、hever、konya、lavender-light、lucas-sandery、mancave、mvt、nette、ng9、nicu、pappu687、paranoiq、pepa-linha、pokorny、price、rmsoft、rmsoft_blue、rmsoft_blue-dark、win98。
以启用 nette 主题为例(主题源文件在 designs/nette/adminer.css,实测下载 28023 字节):
curl -fsSL -o /var/www/html/adminer/adminer.css \
https://raw.githubusercontent.com/vrana/adminer/master/designs/nette/adminer.css
curl -s http://localhost/adminer/index.php | grep -oE "adminer\.css[^\"']*"
实测回显(页面自动加载主题覆盖层):
adminer.css?v=462079817
自定义微调则直接编辑站点目录的 adminer.css(或从空白文件写起):
echo "body { font-size: 14px; }" > /var/www/html/adminer/adminer.css
💡 说明:主题与自定义 CSS 是同一个挂载点——想「官方主题打底 + 自己微调」,把主题文件下载下来后在其尾部追加自定义规则即可;
?v=参数是内容指纹,内容变化后浏览器缓存自动失效(实测同一主题文件在两处部署得到相同指纹 462079817)。
4.4 PHP 运行参数(上传、会话)
Adminer 的导入功能走 PHP 上传通道,默认值偏小(Ubuntu 22.04 php8.1 FPM 实测):
upload_max_filesize=2M
post_max_size=8M
memory_limit=-1
session.gc_maxlifetime=1440
导入大 SQL/CSV 时在 FPM 的 php.ini 调大 upload_max_filesize 与 post_max_size(改法与逐项说明见《Ubuntu 22.04 安装 Adminer 6.1.2 指南》7.1 节);session.gc_maxlifetime=1440(24 分钟)决定登录态空闲过期时间,需要长会话时调大并重启 FPM。
五、插件体系详解
5.1 Plugin 基类与钩子机制
Adminer 6 的插件是继承 Adminer\Plugin 基类的 PHP 类,通过覆写钩子方法介入应用生命周期。官方插件源码中的钩子用例(plugins/ 目录实查):
| 钩子方法 | 触发时机 | 官方插件用例 |
|---|---|---|
loginFormField(...) | 渲染登录表单字段 | 预填/改写服务器字段 |
login($username, $password) | 凭据校验阶段 | AdminerLoginIp 做 IP 白名单 |
dumpFilename($identifier) | 生成导出文件名 | AdminerDumpDate 拼接时间戳 |
headers() / csp() | 输出 HTTP 头 | 安全相关插件 |
tablesPrint(...) | 渲染库表菜单 | database-hide 隐藏指定库 |
所有插件实例被 Adminer\Plugins 聚合对象收集,同名钩子按装配顺序依次调用——聚合对象正是通过自托管入口的 adminer_object() 函数交给应用本体的(5.2 实测)。
5.2 加载流程与启用形态
自托管场景的标准做法(官网插件页与源码 README 一致):写一个自定义入口 index.php,定义 adminer_object() 返回 Adminer\Plugins 实例,再引入 adminer.php。本文实测环境即采用此形态:
<?php
// /var/www/html/adminer/index.php —— 自托管入口:装配插件后启动
function adminer_object() {
require_once 'plugins/dump-date.php';
require_once 'plugins/login-ip.php';
return new Adminer\Plugins(array(
new AdminerDumpDate(),
new AdminerLoginIp(array('127.', '::1', '10.89.58.')),
));
}
require 'adminer-6.1.2.php';
部署后验证(访问 index.php 而非 adminer-6.1.2.php,插件即已装配):
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://localhost/adminer/index.php
curl -s http://localhost/adminer/index.php | grep -oE '<title>[^<]+</title>'
实测回显:
HTTP 200
<title>Login - Adminer</title>
⚠️ 注意:自托管后对外访问地址应改为 index.php(或配置 Web 服务器目录默认页),直接访问 adminer-6.1.2.php 会绕过插件装配——加固时可在 Web 层屏蔽对 adminer-6.1.2.php 的直接访问。
💡 说明:官方容器发行版在这套机制上做了工程化封装——入口自动扫描启用目录、支持用环境变量列无参插件、并提供启用文件生成器(对带必填参数的插件打印完整模板),部署形态细节见《Adminer 6.1.2 Docker 部署指南》第八章。带参插件的启用文件模板标准形态如下(以官方文档记载的
login-servers为例,模板格式实测):return new AdminerLoginServers( $servers = ???, $driver = 'server' );把
???换成实际参数即可。
5.3 内置插件清单(51 个,按用途分类)
官方源码 plugins/ 目录实查 51 个插件文件(2026-10-20),按用途归类:
| 分类 | 插件(文件名去掉 .php) | 说明 |
|---|---|---|
| 登录与访问控制 | login-ip、login-otp、login-passkey、login-ssl、login-table | IP 白名单、TOTP 二次验证、Passkey、强制 SSL 连接、限制可用登录表 |
| 导入导出 | dump-alter、dump-bz2、dump-date、dump-json、dump-xml、dump-zip、import-csv | 导出格式扩展(JSON/XML/压缩包)、文件名加日期、ALTER 方式导出、CSV 导入 |
| 编辑体验 | edit-foreign、edit-textarea、enum-option、file-upload、select-email、select-expression、select-foreign、select-image | 外键下拉、文本域编辑、枚举选择、图片/文件上传与显示 |
| 查询辅助 | highlight-codemirror、highlight-monaco、highlight-prism、sql-log、sql-url-length、sql-gemini | SQL 高亮(三选一)、SQL 执行日志、Gemini AI 辅助 |
| 界面与导航 | adminer.js、dark-switcher、database-hide、designs、frames、menu-links、remote-color、row-numbers、tables-filter、table-structure、table-indexes-structure、backward-keys、before-unload | 全局 JS 注入、暗色切换、隐藏库表、行号、表格过滤、离开确认 |
| 工具与杂项 | config、editor-setup、editor-views、foreign-system、name-patterns、slugify、timeout、version-github、version-noverify | 常量配置化、Editor 配套、命名模式校验、会话超时、版本检查开关 |
💡 说明:
config插件值得一提——它把常量配置从「改入口文件」变成「插件参数」,适合不想动 index.php 的场景。完整官方插件文档与外部贡献插件见官方插件页 https://www.adminer.org/plugins/(2026-10-20 可访问)。
5.4 扩展驱动(8 个)
官方源码 plugins/drivers/ 目录实查 8 个扩展驱动:clickhouse.php、elastic.php(Elasticsearch/OpenSearch)、firebird.php、igdb.php、imap.php、mongo.php(MongoDB)、redis.php、simpledb.php。驱动插件的装配方式与普通插件相同(adminer_object() 返回实例);启用后登录页「系统」下拉出现对应引擎选项。PHP 侧相应扩展需求:MongoDB 需 mongodb 扩展、Oracle 需 oci8、Firebird 需 interbase(官方容器发行版文档声明的扩展对应关系,实查 2026-10-20)。
六、常用插件实操
6.1 login-ip:登录 IP 白名单(全链实测)
login-ip 是生产加固首选。源码机制(plugins/login-ip.php 实查):构造参数 $ips 为 IP 前缀数组(默认 array('127.', '::1'),即只允许本机),$forwarded_for 为反代场景的 X-Forwarded-For 前缀数组;login() 钩子对 REMOTE_ADDR 做前缀匹配,不匹配即拒绝登录。
启用(5.2 的 index.php 已装配 new AdminerLoginIp(array('127.', '::1', '10.89.58.')),即允许本机与 10.89.58 网段)。
REMOTE_ADDR 形态先行确认——白名单前缀必须匹配真实形态,两种运行环境实测对照:
# Apache 原生环境:写探针输出 REMOTE_ADDR 后从远端访问
printf '<?php echo $_SERVER["REMOTE_ADDR"];' > /var/www/html/adminer/probe.php
curl -s http://<服务器IP>/adminer/probe.php
实测回显对照:
Apache + PHP-FPM,远端经 NAT/映射访问:10.89.58.1 (点分 IPv4)
Apache + PHP-FPM,本机访问:127.0.0.1
PHP 内置服务器(php -S 监听 [::]:8080),远端访问:::ffff:10.89.58.1 (IPv4 映射形式)
放行实测(白名单含 10.89.58. 前缀,远端 IP 10.89.58.1 登录):凭据正确,实测进入:
<title>Database: shop - mysql1 - Adminer</title>
拒绝实测(白名单改为仅本机 array('127.', '::1') 后,同一远端再登录):凭据依然正确,实测被拒:
<title>Login - mysql1 - Adminer</title>
class='error'>Invalid credentials.
⚠️ 注意:白名单前缀形态错误(如运行环境是 IPv4 映射形式却只写了点分前缀)会导致所有人都登录不了,表现为「凭据明明正确却报 Invalid credentials」——先跑探针确认
REMOTE_ADDR实际形态再写前缀。走 Nginx 反代时需改用$forwarded_for参数匹配 X-Forwarded-For(源码注释明确:代理会把客户端 IP 追加到该头)。
6.2 dump-date:导出文件名自动加时间戳(实测)
机制(plugins/dump-date.php 实查):覆写 dumpFilename(),把库名与 SELECT NOW() 拼成文件名。启用后(本文环境已装配)导出 shop 库为下载模式,实测响应头:
Content-Disposition: attachment; filename=shop-2026-10-19-19-25-16.sql
无该插件时文件名只有 shop.sql;备份习惯用「库名+日期」归档的团队开了它就不用手动改名。
6.3 自定义插件实战:隐藏服务器字段(实测)
需求:登录页不显示「服务器」输入框,把目标库固定为 mysql1(防止登录页被当作任意主机数据库扫描跳板)。写自定义插件类文件 plugins/fixed-server.php:
<?php
// 自定义插件:隐藏登录页「服务器」字段并固定目标服务器
final class AdminerFixedServer extends Adminer\Plugin {
public function __construct(private Adminer\Adminer $adminer) { }
public function loginFormField(...$args): string {
return (function (...$args): string {
$field = $this->loginFormField(...$args);
return preg_replace(
"~<input name='auth\[server\]'[^>]*>~",
"<input type='hidden' name='auth[server]' value='mysql1'>",
$field
);
})->call($this->adminer, ...$args);
}
public function description() {
return "Hide the server input field and pin the target server.";
}
}
在 index.php 的装配数组中追加实例:
require_once 'plugins/fixed-server.php';
return new Adminer\Plugins(array(
new AdminerDumpDate(),
new AdminerLoginIp(array('127.', '::1', '10.89.58.')),
new AdminerFixedServer(new Adminer\Adminer()),
));
写法要点(实测归纳):插件持有 Adminer\Adminer 默认实现实例,loginFormField() 里用闭包重绑定(->call($this->adminer, ...))转发原始调用再做正则改写——这是官方插件生态通行的「包装默认实现」手法;类名与文件名不必一致,入口返回插件实例即可装配。
部署后验证登录页(实测回显):服务器字段已从文本输入框变为隐藏域——
<input type='hidden' name='auth[server]' value='mysql1'>
登录功能不受影响(实测用 root/q1w2e3r4 登录 mysql1 成功,页面标题):
<title>Database: shop - mysql1 - Adminer</title>
💡 说明:这个插件的实战价值在「预填(可改)」与「隐藏固定(不可改)」之间划清了边界:对外提供固定库管理入口时用后者,多库运维自用时用前者。同样的手法可推广到隐藏数据库字段、注入说明文字等任意登录页定制。
七、Adminer Editor 变体
Editor 是与主程序同代码库发布的「最终用户数据编辑器」变体(约 317 KB):隐藏表结构/触发器/权限等管理功能,聚焦数据浏览、外键友好显示与表单化编辑,适合给业务人员做受限数据维护。
部署实测(与主程序并列放站点目录):
curl -fsSL -o /var/www/html/adminer/editor-6.1.2.php \
https://github.com/vrana/adminer/releases/download/v6.1.2/editor-6.1.2.php
curl -s -o /dev/null -w "EDITOR_HTTP %{http_code}\n" \
http://localhost/adminer/editor-6.1.2.php
curl -s http://localhost/adminer/editor-6.1.2.php | grep -oE '<title>[^<]+</title>'
实测回显:
EDITOR_HTTP 200
<title>Login - Editor</title>
Editor 与标准版的差异(登录后体验):菜单只有「选择数据 / 新建记录 / 搜索」,无「表结构 / 触发器 / SQL 命令 / 用户权限」入口;外键列自动显示关联表的名称字段而非裸 ID。配合 login-table 插件可进一步限定可见表。
八、安全加固清单
按暴露面从外到内的顺序,给出 Adminer 生产加固的逐项实操汇总(各项均已在本文或部署篇实测):
- 网络层收敛:Adminer 不暴露公网,仅内网/VPN 可达;Nginx 反代统一 HTTPS(反代与 fastcgi 形态做法见《Adminer 6.1.2 Docker 部署指南》4.4 节)。
- IP 白名单:
login-ip插件(6.1 节全链实测),注意先确认 REMOTE_ADDR 形态再写前缀,反代场景用 X-Forwarded-For 匹配。 - 固定/隐藏服务器字段:
Adminer\SERVER常量(4.1 节)或自定义插件隐藏(6.3 节实测),杜绝登录页被用作任意主机扫描器。 - 二次验证:
login-otp(TOTP)与login-passkey官方插件按 5.2 装配;管理类 Web 入口建议至少启用其一。 - 账号原则:Adminer 自身无用户体系,登录凭据即数据库账号——为 Adminer 建专用低权限数据库账号(如只读账号给查询场景),不复用 root;示例演示口令之外的正式口令一律走密钥管理。
- 会话与传输:HTTPS 下配合
auth[permanent](永久登录 Cookie)慎用;空闲过期由session.gc_maxlifetime控制(4.4 节默认 1440 秒实测)。 - 入口收敛与版本暴露面:自托管后把对外入口收敛到 index.php(5.2 节 ⚠️),Web 层屏蔽 adminer-6.1.2.php 直连;页脚会显示 Adminer 版本号,保持跟进 6.x 最新补丁(v6.1.2 修复了 5.0.0 以来的多处回归,见 Releases 说明);不用的驱动瘦身版(
-mysql-en.php)可减小攻击面。
九、常见问题(FAQ)
Q1:装配了插件但没有任何效果?
排查顺序:访问的是否 index.php(直接访问 adminer-6.1.2.php 不经过 adminer_object(),插件不生效);adminer_object() 是否 return 了插件实例数组(只 require 类文件不算装配);PHP 语法是否通过(php8.1 -l /var/www/html/adminer/index.php 核对)。
Q2:插件类 extends Adminer\Plugin 报类不存在?
adminer_object() 在应用本体加载过程中被调用,Adminer\Plugin 彼时已定义,正常装配不会报错;若你在独立 CLI 脚本里加载插件,需要自行兜底:class_exists(\Adminer\Plugin::class) || class_alias(stdClass::class, \Adminer\Plugin::class)(官方工具 plugin-loader.php 的同款处理,源码实查)。
Q3:自定义插件改了登录表单后登录 500?
多为正则替换后表单结构残缺(如误删 token 隐藏域)。用 6.3 的最小替换法:只改目标 input 的 type/value 属性,不动表单其余部分;替换后先 curl 登录页核对 HTML 再上真库。
Q4:白名单写对了还是登录不了?
先确认两件事:Web 服务器是否经 NAT/反代(REMOTE_ADDR 可能是网关 IP 或 IPv4 映射形式,跑 6.1 的探针);是否走反代而 REMOTE_ADDR 恒为反代本机——此时应改配 $forwarded_for 参数匹配 X-Forwarded-For。
Q5:想要的主题/插件在官方源码里找不到?
插件清单随版本演进(51 个以源码 plugins/ 目录实查为准),个别文档提到的插件可能已并入核心或改名;主题同理以 designs/ 目录为准,外部贡献资源见官方插件页与 designs 页实时列表。
十、参考链接
- Adminer 官方插件页:https://www.adminer.org/plugins/
- 官方插件源码目录:https://github.com/vrana/adminer/tree/master/plugins
- 官方设计主题目录:https://github.com/vrana/adminer/tree/master/designs
- Adminer 6.1.2 Releases:https://github.com/vrana/adminer/releases
- 站内配套文档:《Adminer 6.1.2 介绍与选型指南》(选型与架构)、《Ubuntu 22.04 安装 Adminer 6.1.2 指南》(原生部署与 PHP 参数)、《Adminer 6.1.2 Docker 部署指南》(容器形态与环境变量)