lcoy / cipher
Password-gated [protected] BBCode with real-time unlock for Flarum.
Requires
- php: ^8.3
- flarum/core: ^2.0.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
为 Flarum 提供密码保护的 [protected] BBCode 标签,支持多种可见条件与实时解锁体验。
- 密码保护内容,未解锁时仅显示锁定卡片(带流动光效)
- 可选可见条件:点赞、回复、关注作者、关注本帖、帖子赞数、定时可见
- 解锁弹窗内实时显示每个条件的满足状态(✓ 已满足 / ✗ 未满足)
- 实时解锁:时间条件到点自动公开;点赞数达标通过 WebSocket(flarum-pusher)实时刷新
- 可视化编辑弹窗:发帖工具栏 🔒 按钮内提供勾选式条件、快捷时间下拉,无需手写 BBCode
- 作者、管理员与版主无需密码,直接查看原始内容
仓库地址
- Gitee:https://gitee.com/lcoy/flarum-cipher
- GitHub:https://github.com/Lcoy2004/Flarum-cipher
- Packagist:https://packagist.org/packages/lcoy/cipher
安装
composer require lcoy/cipher
启用扩展后,在后台「扩展」页进入 Cipher 设置,可按需配置。
前端构建(可选)
如果扩展自带的 js/dist 不适用,可从源码重新构建前端:
cd js
npm install
npm run build
基本用法
在帖子内容中使用 [protected] 标签包裹需要隐藏的内容:
[protected password="123456"]只有输入密码才能看到的内容[/protected]
password:解锁密码(留空则使用管理员设置的默认密码;默认密码变更后,对所有留空的内容立即生效)title:锁定卡片上显示的标题(可选)
未解锁的访客看到的是一张锁定卡片,点击「解锁」输入密码后即可查看内容。若该内容没有单独设置密码,卡片上会直接标注当前默认密码,解锁弹窗也会自动填入,读者点击「确认解锁」即可查看,无需询问作者。
使用编辑器按钮
发帖/回复的工具栏有 🔒 按钮,打开可视化编辑弹窗:
- 选中要隐藏的文字,点击 🔒
- 输入密码(留空则使用默认密码;密码框下方会直接显示当前的默认密码,方便随时核对)
- 勾选需要的可见条件:点赞、回复、关注作者、关注本帖
- 可选设置「帖子赞数达到 N」与「指定时间后可见」(带 1h / 6h / 12h / 1d / 3d 快捷时间下拉)
- 点击「确定」即可插入或更新
[protected]标签
再次点击已存在的 🔒 标签可进入编辑模式,原条件会自动回填。若该内容已经设置过密码,密码框会额外提供「改用默认密码」勾选项——勾选后原密码被清除,改为使用后台设置的默认密码。
可见条件
除密码外,还可以为内容附加额外条件。条件之间为「并且」关系,全部满足才能解锁。
| 条件 | 示例 | 说明 |
|---|---|---|
| 点赞 | like="1" |
必须给本帖点过赞 |
| 回复 | reply="1" |
必须在本讨论中回复过(隐藏/删除的回复不计) |
| 关注作者 | follow="1" |
必须关注帖子作者(依赖提供 user_followers 表的扩展,如 ianm/follow-users) |
| 关注本帖 | followDiscussion="1" |
必须关注本讨论(依赖 flarum-subscriptions,订阅状态为 follow) |
| 赞数达标 | minlikes="10" |
本帖总赞数达到 N 个 |
| 定时可见 | time="2026-08-09 12:00" |
到指定时间后自动公开,无需密码 |
| 相对时间 | time="+2d" / time="12h" / time="30m" / time="45s" |
相对发帖时间的偏移,保存时归一化为绝对时间 |
说明:
follow(关注作者)和followDiscussion(关注本帖)是两种不同的关注行为。前者跟随作者,后者订阅当前讨论。两者可同时启用。
组合示例:
[protected password="123456" title="福利内容" like="1" reply="1" follow="1" followDiscussion="1" minlikes="3" time="2026-08-09 12:00"]内容[/protected]
该内容要求:当前时间已到 2026-08-09 12:00、已点赞、已回复、已关注作者、已关注本帖、帖子满 3 个赞,再输入密码才可查看。
条件状态实时显示
锁定卡片与解锁弹窗都会列出每条已配置的条件:
- ✓(绿色)表示当前已满足
- ✗(红色)表示尚未满足
实时更新
- minlikes(赞数):启用
flarum-pusher后,其他人点赞导致赞数达标时,正在浏览的访客会实时看到 ✗ 变为 ✓,无需刷新 - time(定时):到点后锁定卡片自动变为公开内容,无需刷新或输入密码
实时更新由后端 PushPostUpdate 监听 PostWasLiked / PostWasUnliked 事件,并通过 Pusher 在 public 频道广播 cipherPostUpdate 事件;前端订阅该事件后调用 GET /api/cipher/status 拉取最新条件状态。time 条件则在前端按 data-cipher-target 调度一次性定时器,到点自动重渲染。
实时通道按需启用:未安装
flarum-pusher时不会触发任何推送,扩展仍可正常工作;同时监听器对失败推送做了静默处理,绝不会因 Pusher 故障而打断原帖请求。
权限说明
- 帖子作者、管理员、拥有
discussion.moderate权限的版主:直接看到原始内容,不显示锁定卡片 - 访客是否允许解锁,由后台设置控制(默认允许)
管理员设置
后台「Cipher」设置页:
| 设置 | 说明 | 默认 |
|---|---|---|
| 允许访客解锁 | 关闭后,只有登录用户才能解锁受保护内容 | 开启 |
| 默认密码 | 作者将密码留空时使用的密码。修改后对所有留空的内容立即生效;已单独设置过密码的内容不受影响 | cipher |
默认密码会在锁定卡片与编辑弹窗中对所有用户显示(便于作者随时查看,避免遗忘)。因此依赖它的受保护内容相当于「点开即可见」——需要真正保密的内容,请作者单独设置密码。
安全说明
- 作者单独设置的密码在保存帖子时即被单向哈希(bcrypt),数据库、前端与任何接口都不会出现明文
- 默认密码是论坛级的共用回退值,会下发给前端供查看,不适合用于真正需要保密的内容
- 锁定卡片的渲染结果不会包含密码哈希
- 解锁接口按「帖子 + IP」限流:10 分钟内最多 10 次失败尝试
常见问题
问:作者设置的密码,读者输入正确就一定能解锁吗? 能。保存与解锁两侧都会自动去除密码首尾的空格(手机输入法常误加空格,不会因此解不开);密码内部的空格、大小写、中文等均按原文精确匹配。密码超过 72 字节时 bcrypt 会截断,但哈希与验证两侧截断一致,不影响解锁。
问:忘记密码了怎么办? 作者或管理员可直接查看内容。此外要看该内容是哪种密码:
- 留空密码(使用默认密码)→ 管理员在后台改默认密码后立即生效
- 作者单独设置过密码 → 密码以哈希形式固化在该帖中,改默认密码无效,需要作者重新编辑该内容:输入新密码,或勾选「改用默认密码」清除原密码
问:作者说没设置密码,但输入默认密码打不开? 说明该内容并非「留空密码」,而是曾经单独设置过密码(即使作者后来清空了密码框,编辑弹窗默认也会保留原密码)。请作者重新编辑该内容并勾选「改用默认密码」,即可切回默认密码。
问:设置了时间条件,密码还有用吗? 有用。到点前需要密码(且密码正确才解锁);到点后内容自动公开,不再需要密码。
问:like、reply、follow、followDiscussion 条件在什么时机生效?
解锁接口每次都会重新校验,执行对应操作(点赞 / 回复 / 关注作者 / 关注本帖)后无需重新输入密码逻辑,但需要重新提交解锁;配合 WebSocket 时,条件状态会实时刷新。
问:为什么我满足所有条件却仍提示未满足?
请确认是在当前账号下操作:like / reply / follow / followDiscussion 判断的是当前登录用户自己的行为;minlikes 判断的是帖子总赞数。访客账号无法满足点赞 / 回复 / 关注类条件。
问:follow 和 followDiscussion 有什么区别?
follow 关注的是帖子作者(依赖提供 user_followers 表的扩展,如 ianm/follow-users);followDiscussion 关注的是当前讨论(依赖 flarum-subscriptions,订阅状态为 follow)。两者独立判定,可同时启用。
问:followDiscussion 启用了但提示未满足?
请到帖子右上角的订阅菜单确认已选择「关注」(follow)状态。「忽略」或默认不订阅都不会算作已关注。
许可证
MIT