游客身份与燃币体系调研:匿名评论、ID 绑定与燃币门槛的通用方案 + 2aran.com 落地设计
写在前面:前半部分(二、三节)是与具体站点无关的通用方案与行业做法;第四节起是针对 2aran.com 现有架构的设计建议,属技术取舍,不是法律意见,合规/实名口径以官方最新规定为准。
一、先给结论
游客身份用「签名 Cookie 里的随机 UUID」当主键,IP 和设备指纹只当反滥用的弱信号;燃币用「只增不改的流水账本」当正本,余额只是它的物化缓存。
四个最容易踩的坑,先标出来:
| 常见做法 | 问题 | 稳妥替代 |
|---|---|---|
| 用 IP 当游客唯一 ID | NAT / CGNAT / 校园网多人共享一个 IP;移动网络 IP 频繁漂移 | IP 只用于限流与关联,主身份放签名 Cookie |
| 上来就接商业版设备指纹 | 指纹属个人信息(合规面)、开源版精度有限、维护成本高 | 先不接,出现刷分再后置加 |
| 燃币直接改余额字段 | 无法审计、并发下易错账、刷分难追溯 | 流水账本(ledger)为正本,余额物化 |
| 解锁资源时每次扣分 | 用户重复阅读被反复收费,体验差 | 解锁记一条「权益(entitlement)」,之后永久可读 |
二、事实层:游客(匿名)身份的通用方案
本节为通用技术方案,逐项标注成熟度:成熟通用 / 可选增强 / 有合规约束。
2.1 四类匿名身份载体对比
| 方案 | 稳定性 | 可篡改性 | 跨设备 | 隐私/合规 | 防滥用强度 | 成熟度 |
|---|---|---|---|---|---|---|
| Cookie / localStorage 明文 UUID | 中(清缓存即丢) | 用户可改 | 否 | 低敏感 | 弱 | 成熟通用 |
| 签名 Cookie(HMAC)装 UUID | 中(清缓存即丢) | 不可伪造 | 否 | 低敏感 | 中 | 成熟通用 |
| IP 地址 | 低(共享+漂移) | 不可改但可换 | 部分 | 属个人信息 | 中(限流好用) | 成熟但不宜单用 |
| 设备指纹(Canvas/UA/字体…) | 中高 | 难改 | 否 | 强敏感,按 PII 对待 | 强 | 可选增强 |
核心判断:没有任何单一载体既稳定、又防滥用、又低隐私风险。通用解是分层——签名 Cookie 做主身份(稳定且不可伪造),IP 做限流与关联(已是行业标配),设备指纹按需做反刷的最后一道(默认不开)。
2.2 主身份为什么选签名 Cookie + UUID
- 服务端生成随机 UUID(
crypto.randomUUID()),用 HMAC 密钥签名后写入 Cookie;读取时验签,篡改即失效。 - 优点:无需数据库即可在边缘验证;同一浏览器跨文章稳定;不依赖 IP;天然兼容「先匿名后注册」的绑定。
- 局限:清缓存 / 换浏览器 / 隐身模式会得到新 ID。对「游客评论」这是可接受的——本来就不承诺跨设备身份。
2.3 IP 与设备指纹的正确位置
- IP:取自反代头(Cloudflare 为
cf-connecting-ip)。适合做限流的 subject 和异常关联(同 IP 短时间大量新游客→疑似刷),不适合做身份主键。 - 设备指纹:开源方案如 FingerprintJS(开源版)可做,但开源版精度与商业版差距明显,且指纹在 GDPR/PIPL 语境下通常按个人信息对待。建议默认不采集,只有当刷分/刷评论实际发生时,再作为反作弊弱信号引入,并在隐私说明中披露。
2.4 游客 → 注册的绑定(account linking)通用模式
主流身份平台都把「匿名账号升级为正式账号」做成一等公民:
| 平台 | 机制 | 官方文档关键词 |
|---|---|---|
| Firebase Auth | 先 signInAnonymously 拿匿名 uid,注册时 linkWithCredential 把凭证挂到同一 uid |
Anonymous Auth / Account Linking |
| Supabase Auth | Anonymous Sign-in 拿匿名用户,后续 updateUser 绑定邮箱/OAuth,uid 不变 |
Anonymous Sign-ins |
| Disqus 等评论系 | 游客填昵称+邮箱直接评论,注册后按邮箱归并历史 | Guest commenting |
通用范式(与平台无关):
- 匿名期:所有写操作(评论、点赞)记在
guest_id名下; - 注册/登录瞬间:若请求里带着有效
guest_idCookie,写一条guest_id → user_id绑定,并把该 guest 的历史内容user_id改写为正式 id(幂等、可重入); - 绑定后清除 guest Cookie,后续走正式会话。
要点:绑定要幂等(同一 guest 多次触发只生效一次)、要防「抢绑」(一个 guest_id 只能绑第一个完成绑定的账号)。
三、事实层:燃币体系的通用方案
本节为通用设计范式,与具体站点无关。
3.1 正本是账本,不是余额
成熟燃币/虚拟货币体系的共识:用只增不改(append-only)的流水账本记每一笔变动,余额是账本的物化(materialized)结果,而不是直接 UPDATE balance = balance + n。
point_ledger (不可变流水) user_points (物化余额, 可重算)
───────────────────────── ──────────────────
user_id | delta | reason | ref | ts user_id | balance | updated_at
A | +50 | register | - | t0 A | 58
A | +5 | checkin | d1 | t1
A | +3 | comment | c9 | t2
A | -50 | unlock | r7 | t3 → 扣分=再插一条负数,不改历史
好处:可审计、可对账、可追溯刷分、并发安全(靠唯一约束做幂等),余额错了能从账本重算。
3.2 赚取(earn)与消费(spend)设计
| 维度 | 通用做法 | 反作弊要点 |
|---|---|---|
| 注册奖励 | 一次性发放 | 每账号仅一次(唯一约束 ref=register) |
| 每日签到 | 按自然日发放 | ref=checkin:YYYY-MM-DD 唯一,防重复 |
| 评论/互动得分 | 小额、设每日上限 | 删除/被判垃圾应回收或不计;按 IP+用户双限 |
| 消费解锁 | 扣分 + 记权益 | 余额不足拒绝;解锁幂等,重复解锁不重复扣 |
| 游客 | 零燃币、不可赚不可花 | 从入口就拦截,避免刷注册套利 |
3.3 内容门槛(gated content)的三种形态
| 形态 | 说明 | 适用 |
|---|---|---|
| 全文燃币墙 | 整篇/整个资源需燃币解锁 | 高价值资源、下载类 |
| 部分预览 + 解锁 | 前段免费,正文需燃币 | 长文、教程 |
| 阶梯角色门槛 | 按角色(游客/会员/信任)放行,燃币只是其一 | 与 site_users.role 配合 |
通用要点:解锁后写一条权益(entitlement)记录,之后该用户重复访问直接放行、不再扣分;门槛判定放服务端,前端只做展示。
四、研判:对 2aran.com 的落地设计
以下是基于现有代码架构的设计建议,落在技术取舍与表结构上,不是法律意见,也不是最终实现。 现状盘点:站点已有 HMAC 签名 Cookie 会话(
lib/edgeSession.js的signSession/verifySession)、getClientIp(cf-connecting-ip)、SHA-256、D1 限流表api_rate_limits、统一用户目录site_users(member/trusted/blocked)、评论表article_comments,且评论 API 当前强制登录(无 user 直接 401)。这套基础设施几乎覆盖本需求所需的全部原语。
4.1 游客身份:复用签名 Cookie,新增 guest_id
- 复用
edgeSession已有的 HMAC 签名能力,新增一个tuaran_guest签名 Cookie,载荷为{ gid: randomUUID(), iat },长有效期(如 180 天)。 - 首次匿名写操作(评论)时若无 guest Cookie 则签发;后续验签取
gid作主身份。 - IP(
getClientIp)继续只做api_rate_limits的 subject 与异常关联,不进身份主键。 - 设备指纹本期不做,列入「观望」。
4.2 让评论支持游客(改造 app/api/comments/route.js)
当前 POST 在 getUserFromRequest 为空时直接 401。改造方向:
| 项 | 登录用户 | 游客 |
|---|---|---|
| 身份 | user.id |
guest:<gid> |
| 作者名 | 用户名/头像 | 「游客 + 短哈希」占位 |
| 限流 | 现有 user+IP 双限 | 更严(如 5m 内 3 条、且新 guest 首条可加审核/敏感词) |
| 落库 | article_comments 原样 |
同表,user_provider='guest',user_id='guest:<gid>' |
| 封禁 | getUserRole==='blocked' 拦截 |
按 IP/guest 维度限流兜底 |
合规提示(需自行核实最新法规):中国《互联网跟帖评论服务管理规定》对跟帖评论服务存在「后台实名、前台自愿」一类要求。是否、以及如何对游客评论落实,属法规与运营判断,本文不下结论,仅提示在「未能验证清单」里跟进。
4.3 绑定流程:注册/登录时归并 guest
在 4 个登录入口(github/google 回调、邮箱 login/register)成功后统一加一步:
若请求带有效 tuaran_guest Cookie:
1. INSERT OR IGNORE guest_bindings(gid, user_id, bound_at) -- gid 唯一,抢绑只第一个生效
2. UPDATE article_comments SET user_id=?, user_provider=? WHERE user_id='guest:'||gid -- 迁移历史评论
3. 清除 tuaran_guest Cookie
游客无燃币,故绑定时无燃币迁移——这正好让绑定逻辑更简单。
4.4 燃币体系:四张表 + 权益解锁
建议新增 migration(接在 0026 之后):
-- 燃币流水(正本,只增不改)
CREATE TABLE point_ledger (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
delta INTEGER NOT NULL,
reason TEXT NOT NULL, -- register|checkin|comment|unlock|admin
ref TEXT NOT NULL DEFAULT '', -- 幂等键,如 checkin:2026-06-22 / unlock:r7
created_at INTEGER NOT NULL
);
CREATE UNIQUE INDEX idx_point_ledger_idem ON point_ledger(user_id, reason, ref);
-- 物化余额(可由账本重算)
CREATE TABLE user_points (
user_id TEXT PRIMARY KEY,
balance INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL
);
-- 资源门槛配置
CREATE TABLE gated_resources (
resource_key TEXT PRIMARY KEY,
cost_points INTEGER NOT NULL DEFAULT 0,
min_role TEXT NOT NULL DEFAULT 'member',
created_at INTEGER NOT NULL
);
-- 解锁权益(解锁一次,永久可读)
CREATE TABLE resource_unlocks (
user_id TEXT NOT NULL,
resource_key TEXT NOT NULL,
unlocked_at INTEGER NOT NULL,
PRIMARY KEY (user_id, resource_key)
);
赚取/消费规则(建议初值,全部可后台配):
| 动作 | 燃币 | 幂等键 / 上限 |
|---|---|---|
| 注册 | +50 | register(每账号一次) |
| 每日签到 | +5 | checkin:YYYY-MM-DD |
| 有效评论 | +2 | 每日上限 +20,被判垃圾不计 |
| 解锁资源 | −cost_points |
余额不足拒绝;已解锁直接放行 |
| 站长手动 | ± | reason='admin',后台操作 |
解锁判定(服务端):游客 → 401「登录后用燃币解锁」;会员已在 resource_unlocks → 放行;余额≥cost → 扣分(插 ledger 负数 + upsert 余额 + 插 unlock,建议一个事务/批处理)→ 放行;不足 → 提示「再赚 X 分」。
4.5 跟进 / 不跟进 / 观望
- 跟进:签名 Cookie
guest_id+point_ledger/user_points/gated_resources/resource_unlocks四表 + 解锁权益判定。复用现有 HMAC、限流、site_users,新增面很小。 - 不跟进:以 IP 为身份主键;直接改余额字段不留账本;解锁每次扣分;上来接商业版设备指纹。
- 观望:设备指纹强反刷(等真出现刷分再加);燃币提现/换现金(涉及会计与合规,门户站不必要);跨设备游客身份(价值低于成本)。
4.6 下一步(建议分两期)
- 一期·游客评论:新增
tuaran_guest签名 Cookie +guest_bindings表;改造commentsPOST 接受游客(更严限流 + 首条审核可选);登录入口加归并步骤。 - 二期·燃币解锁:上四张燃币表 + 赚取入口(注册/签到/评论)+ 资源解锁 API + 前端燃币墙组件 +
/admin燃币与门槛配置页。
五、行业横向参照
同类做法横向参考,非任一产品实际数据/实现细节,仅示意形态。
| 产品 / 体系 | 游客身份做法 | 绑定 | 燃币/门槛 |
|---|---|---|---|
| Disqus | 游客填昵称+邮箱即评 | 按邮箱归并 | 无燃币,靠声誉/审核 |
| 知乎 / 掘金类社区 | 需登录为主,匿名能力有限 | 账号体系内 | 盐值/矿石类虚拟燃币 + 解锁/兑换 |
| V2EX | 铜币/铸币燃币 | 账号内 | 发帖/回复得币,置顶等消费 |
| Firebase / Supabase | 匿名 Auth 拿临时 uid | 升级绑定,uid 不变 | 不含燃币,仅身份层 |
可借鉴的结构性共识:身份层(匿名→绑定)与燃币层(账本→门槛)解耦;游客只在身份层存在,燃币层从注册才开始。
六、未能验证的事实清单
| 未验证项 | 现状 | 潜在获取路径 |
|---|---|---|
| 游客评论的实名合规口径 | 《互联网跟帖评论服务管理规定》存在「后台实名、前台自愿」类要求,是否适用个人站、如何落实未下结论 | 国家网信办官方规定原文 + 法务/运营判断 |
| 开源版设备指纹的实际精度 | 仅知开源版弱于商业版,无量化基准 | FingerprintJS 官方文档与开源仓库说明 |
| Firebase/Supabase 匿名绑定最新 API 细节 | 按公开文档口径,版本可能变动 | 各自官方 Auth 文档 |
| D1 多表写的事务/批处理保证 | 解锁需「扣分+记权益」原子完成,D1 事务能力需确认 | Cloudflare D1 官方文档 |
| 燃币初值与上限的运营效果 | 表中为建议初值,未经真实数据校准 | 上线后按行为数据调参 |
七、结语与信息来源
一种设计视角:这件事的复杂度不在「燃币」本身,而在两层解耦——把「匿名→注册」放在身份层、把「赚取→消费」放在燃币层,各自独立演进。对 2aran.com 的幸运之处是身份层的难点(签名 Cookie、限流、用户目录)已经建好,新增的主要是燃币层的四张表和解锁判定。先做游客评论、再做燃币解锁,能让每一期都独立可用、风险可控。
以上为技术方案与设计视角,不是预测,也不是法律意见,更不是最终实现。
信息来源
身份与认证官方文档
- Firebase — Anonymous Authentication
- Firebase — Account Linking
- Supabase — Anonymous Sign-ins
- MDN — HTTP Cookies / Set-Cookie
- MDN — Web Crypto API(HMAC / randomUUID)
设备指纹 / 反滥用
运行时 / 数据
合规(需自行核实最新版本)
站内交叉
- 现有鉴权与会话实践参见本站《2aran.com 站长鉴权实践》调研
- 边缘数据层选型参见本站《Cloudflare D1 vs Supabase》调研
Discussion
讨论
还没有讨论