Adminer 6.1.2 配置与插件详解

Adminer 6.1.2 无传统配置文件,本篇详解其三条配置途径(常量与环境变量、CSS/主题覆盖、插件体系):Plugin 基类与钩子机制、plugins-enabled 加载流程与 plugin-loader 生成器实操,内置 51 个插件与 8 个扩展驱动分类速查,login-ip 白名单(含 ::ffff: IPv4 映射陷阱)与 dump-date 全链实测,自定义「隐藏服务器字段」插件实战,Editor 变体部署与安全加固清单。

AdminerAdminer数据库客户端2026/10/20

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 部署指南》第六章),与本文的自托管配置途径一一对应。

二、前置条件

  1. 已有一个可运行的 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
  1. 插件文件需要从官方源码仓库获取(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
  1. 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-tableIP 白名单、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-geminiSQL 高亮(三选一)、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 生产加固的逐项实操汇总(各项均已在本文或部署篇实测):

  1. 网络层收敛:Adminer 不暴露公网,仅内网/VPN 可达;Nginx 反代统一 HTTPS(反代与 fastcgi 形态做法见《Adminer 6.1.2 Docker 部署指南》4.4 节)。
  2. IP 白名单:login-ip 插件(6.1 节全链实测),注意先确认 REMOTE_ADDR 形态再写前缀,反代场景用 X-Forwarded-For 匹配。
  3. 固定/隐藏服务器字段:Adminer\SERVER 常量(4.1 节)或自定义插件隐藏(6.3 节实测),杜绝登录页被用作任意主机扫描器。
  4. 二次验证:login-otp(TOTP)与 login-passkey 官方插件按 5.2 装配;管理类 Web 入口建议至少启用其一。
  5. 账号原则:Adminer 自身无用户体系,登录凭据即数据库账号——为 Adminer 建专用低权限数据库账号(如只读账号给查询场景),不复用 root;示例演示口令之外的正式口令一律走密钥管理。
  6. 会话与传输:HTTPS 下配合 auth[permanent](永久登录 Cookie)慎用;空闲过期由 session.gc_maxlifetime 控制(4.4 节默认 1440 秒实测)。
  7. 入口收敛与版本暴露面:自托管后把对外入口收敛到 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 页实时列表。

十、参考链接

  1. Adminer 官方插件页:https://www.adminer.org/plugins/
  2. 官方插件源码目录:https://github.com/vrana/adminer/tree/master/plugins
  3. 官方设计主题目录:https://github.com/vrana/adminer/tree/master/designs
  4. Adminer 6.1.2 Releases:https://github.com/vrana/adminer/releases
  5. 站内配套文档:《Adminer 6.1.2 介绍与选型指南》(选型与架构)、《Ubuntu 22.04 安装 Adminer 6.1.2 指南》(原生部署与 PHP 参数)、《Adminer 6.1.2 Docker 部署指南》(容器形态与环境变量)