原作者:Maser,原贴地址:https://www.flinthub.top/thread/129
适用版本:2.0.0(2026-09-23) 插件目录:
plugins/vn_postname/| 后台入口:/admin/vn-postname| 前台入口:/vn-postname/aliases
一、这是什么
一个「用另一个身份发帖」的功能。
社区里有时会有这种需求:想用一个小号发点东西,又不想真的去注册第二个账号、来回切换登录。 本插件让你在自己的账号下挂几个「马甲」身份,发帖时在标题或正文里写一句 @@马甲名, 帖子就会以那个马甲的名义发布。
典型场景
- 用「测评君」这种身份发测评,和主号的技术讨论分开
- 版务用「站务公告」这种中性身份发通知
- 单纯想匿名一点,但不想彻底脱离账号体系
它不是什么
- ❌ 不是匿名发帖 —— 后台能查到「哪个真实用户用了哪个马甲」
- ❌ 不是小号注册 —— 马甲无法登录,只是一个署名身份(不能改资料、看站内信、参与任何需登录的操作)
- ❌ 不能借别人的马甲 —— 只能指派你自己名下的马甲
二、怎么用(用户视角)
第 1 步:先创建马甲
登录后,右上角头像菜单(手机端在菜单里)会多出一项 「我的马甲」,点进去:
- 看到自己名下的马甲列表(形如
(已用 1 / 5)) - 底部「创建马甲」填个名字即可
- 已经不想用的,点「解除归属」(只解除关系,不删账号,已发的帖子也不受影响)
马甲名规则
| 项 | 规则 |
|---|---|
| 长度 | 2 ~ 32 个字符 |
| 可用字符 | 中文、字母、数字、下划线 _、点 .、横线 - |
| 保留词 | 不能含 admin / 管理 / 版主 / 官方 / 客服 / 站长 / 楼主 等 22 个词 |
| 重名 | 不能与任何已存在的用户名重复(包括你自己的其他马甲) |
| 数量 | 每人最多 5 个 |
| 频率 | 每小时最多创建 5 次 |
马甲账号由系统用随机强密码创建,任何人都无法用它登录 —— 它只用来署名。
第 2 步:发帖时写 @@马甲名
在发帖页或回帖框里,标题或正文任意位置写一句 @@马甲名,发布后:
- 帖子作者变成那个马甲
- 帖子数、积分也记在马甲名下(见 §四)
- 默认会把
@@马甲名这段标记从正文里抹掉(后台可关) - 发帖页底部会有一行小提示,列出你名下可用的马甲名,点「管理我的马甲」可跳转
示例
标题:聊聊最近用过的几款机械键盘
正文:@@测评君
先说明一下,以下都是自费购买……
发布后,这篇帖子的作者显示为「测评君」,正文里没有 @@测评君 这几个字。
第 3 步(被拒绝时):改一下再发
如果 @@ 指向的马甲不存在、不属于你、或者你没权限用马甲,发帖会被直接拒绝, 你会看到一个 「发帖被拒绝」 的页面,上面写着:
- 被拒绝的标记是哪个(
@@xxx) - 你名下可用的马甲有哪些(方便你直接改成正确的)
- 你刚填的内容完整保留,改掉那一处就能直接重新提交,不用重写
这个拒绝发生在帖子创建之前,所以不会产生半截数据。
三、后台管理(管理员视角)
入口:后台 → 插件 → 马甲发帖(/admin/vn-postname)
3.1 四个开关
| 设置项 | 默认 | 作用 |
|---|---|---|
| 启用马甲发帖 | 开 | 关闭后所有 @@马甲名 都按普通文本发布,不再改写作者 |
| 允许创建马甲 | 开 | 关闭后用户无法在「我的马甲」页新建马甲,已有马甲仍可正常使用 |
发布后去掉 @@马甲名 标记 |
开 | 关闭则标记会原样留在正文里 |
| 允许使用马甲的用户组 | 空 | 勾选哪些用户组可用。一个都不勾 = 仅管理员可用(管理员始终可用) |
3.2 使用记录
页面下方是最近 20 条使用记录,四列:
| 列 | 含义 |
|---|---|
| 操作者 | 真实用户(谁在用马甲) |
| 马甲身份 | 发出去显示的是谁 |
| 类型 | 发帖 / 回帖 / 创建马甲 |
| 时间 | 操作时间 |
「创建马甲」类型的行会带一个「新建」标记,方便区分「这次是建号」还是「这次是发帖」。
页面顶部还显示 「当前全站共 N 个马甲」,一眼看到规模。
四、2.0.0 改了什么(v1.1.0 → v2.0.0)
这一版不是小修小补:核心行为有破坏性变更,且修掉了 16 个审计发现的问题(含 3 个 P0)。
4.1 ⚠️ 核心行为变更:从「自动建号」改为「归属制」
| 1.1.0(旧) | 2.0.0(新) | |
|---|---|---|
写 @@某个不存在的名字 |
自动创建一个新账号,并以它发帖 | 直接拒绝,提示你去「我的马甲」先创建 |
写 @@别人的马甲 |
能以别人的身份发帖(严重安全缺陷) | 直接拒绝 |
谁能用 @@ |
任何名字 | 只能是你自己名下的马甲 |
allow_create 开关 |
控制「发帖时要不要自动建号」 | 只控制「能不能在『我的马甲』页新建马甲」 |
为什么要改:旧版的自动建号意味着任何人只要在标题里写 @@管理员,就能以管理员身份发帖 —— 这是插件最严重的问题。新版把「马甲」变成一个需要先创建、且归属明确的东西, @@ 从「随便指定一个名字」收紧为「指派我自己的马甲」。
4.2 新增能力
| # | 能力 | 说明 |
|---|---|---|
| 1 | 「我的马甲」前台页 | 列表 / 创建 / 解除归属,一个页面搞定。带 CSRF 保护 |
| 2 | 导航入口 | 头像菜单里新增「我的马甲」(PC 下拉 + 移动端菜单都加了) |
| 3 | 拦截前置 | 越权/不存在在路由分发之前就拦掉,返回 422 拒绝页 —— 帖子根本不创建,没有「先建后删」残留 |
| 4 | 拒绝页带草稿回显 | 你刚写的内容完整保留,改一处就能重提(借鉴了 user_level 插件的错误页范式) |
| 5 | 建号护栏 | 用户名规则校验 + 22 个保留词黑名单(包含式匹配,sys_admin 也会被拦)+ 每人 5 个上限 + 每小时 5 次限流 |
| 6 | 计数与积分归马甲 | 见 4.4 |
| 7 | 归属表 | 新增插件自有表 vnpn_aliases,记录「谁拥有哪个马甲」;旧数据自动回填 |
| 8 | 后台增强 | 显示全站马甲总数;使用记录新增「创建马甲」类型 |
4.3 修掉的问题(16 项)
P0 严重
| 编号 | 问题 | 后果 |
|---|---|---|
| P0-1 | 生命周期类名推导失效(目录名带下划线 → 核心找不到主类) | 停用/卸载插件时核心静默跳过,卸载后数据表残留。已用 class_alias 修掉 |
| P0-2 | 身份冒用 —— 可用 @@管理员用户名 以管理员身份发帖 |
见 4.1,已彻底堵死 |
| P0-3 | 发帖页提示钩子是空实现 | 用户完全不知道有 @@ 这个功能。现已补上提示 + 马甲名列表 + 管理入口 |
P1 重要
| 编号 | 问题 | 修法 |
|---|---|---|
| P1-1 | 三语语言包键不一致(简中缺 1 个键) | 补齐,三语各 66 键,键集合与键序完全对齐 |
| P1-2 | init_after 每请求跑建表语句 |
加戳文件门控,只在首次执行 |
| P1-3 | isAllowed() 不校验用户状态 |
封禁/禁用用户现在会被拒绝 |
| P1-4 | 自动建号零护栏 | 随 4.1 一并移除;建号改走带完整校验链的独立入口 |
P2 一般
| 编号 | 问题 | 修法 |
|---|---|---|
| P2-1 | 全部 12 个文本文件是 CRLF 行尾 | 统一为 LF(与项目约定一致) |
| P2-2 | 发帖数双计、马甲积分不同步 | 见 4.4 |
| P2-3 | 搜索索引条件性不同步 | 改写正文时补一次搜索索引重建 |
| P2-4 | 后台视图双重转义 | 去掉多余的转义 |
P3 轻微
| 编号 | 问题 |
|---|---|
| P3-1 | 版本号三处不同步(plugin.json 1.1.0 / 文件头 1.0.0)→ 统一 2.0.0 |
| P3-2 | uninstall() 无异常保护 → 改为逐表 try/catch |
| P3-3 | @@ 独占一段时会留一个空段落 → 现在会清掉 |
| P3-4 | 后台一个无用的死参数 → 移除 |
| P3-5 | 回帖钩子一个形参未使用 → 已用于积分归属 |
4.4 计数与积分:归到马甲名下
核心逻辑是「谁发的帖,就算谁的」,而马甲发帖时核心默认算在真实用户头上。本插件做了一次归属转移:
| 项目 | 处理 |
|---|---|
| 发帖数 | 先退回真实用户的那一次,再给马甲 +1 → 最终只有马甲 +1,全站总数不虚高 |
| 积分 | 先从真实用户扣掉,扣成功才给马甲加上 → 总量守恒,绝不凭空造分(扣失败则跳过加分并记日志) |
| 回帖 | 核心本来就不给回帖加发帖数,所以只需给马甲加积分 |
| 等级 | 不处理 —— 等级联动由核心/等级插件按各自规则走,本插件只做归属转移 |
五、设计取舍与已知边界
刻意这么设计的
- 马甲只能自己用。归属判断只读插件自己的
vnpn_aliases表,不去猜核心用户表。 - 拒绝发生在创建之前。用
route_before_dispatch钩子而不是「发帖后钩子」,所以不会产生「先建了再删」的脏数据。 - 解除归属不删账号。已发的帖子仍挂在那个马甲名下,历史不被打断。想彻底清理账号需另行处理。
- 不碰等级联动。避免和等级体系/等级插件打架,保持职责单一。
已知边界
- 马甲账号由随机强密码创建,任何人都无法登录 —— 因此你不能用它改资料、看站内信、或做任何需要登录的操作,它只是一个署名身份。
- ⚠️ 马甲名一旦创建就永久占用:在核心眼里马甲是一个真实用户账号,「解除归属」只解除关系、不删账号 (删了会让已发的帖子变成无主)→ 所以同名无法再重建(会提示「该用户名已存在」)。 想换名请用另一个名字重建;旧帖子仍归旧名。
- 后台的「使用记录」只保留最近 20 条展示(数据本身保留,只是页面不翻页)。
质量与兼容
- 三语完整支持:简体中文 / 繁体中文 / English(各 66 个语言键,零缺键,键集合与键序一致)
- 主题适配:前台两个页面(「我的马甲」、拒绝页)只用核心既有的
mn-*工具类,不引入任何插件自有样式 → 自动跟随 9 套主题(含夜间模式)。插件唯一的 CSS 是后台样式,按规范 §11.10 后台不提供--mn-*变量, 故使用后台基调色(与核心admin.css一致),不影响前台主题。 - 零内联:无
<style>/<script>/on*=内联属性 - 已通过:
php -l全量、i18n 三语比对、零内联扫描、HTTP 端到端冒烟 37 项全绿、直接调用层回归 28 项全绿 - 插件版本:
2.0.0(plugin.json/Plugin.php/AdminController.php三处一致)