防垃圾评论

防垃圾评论安全防护

版本 v1.0.01· 胡思乱想 · 3 次获取 · 安全防护
集成Akismet云端智能检测与本地规则引擎,在发帖/回帖前拦截垃圾评论、广告灌水、恶意链接。支持自定义关键词黑名单、链接数量限制、最小内容长度
¥2.50抵扣
一次购买,永久使用

详情介绍

Akismet 防垃圾评论插件

在社区发帖 / 回帖前置拦截垃圾评论、广告灌水、恶意链接。集成 Akismet 云端 API + 本地规则引擎 双层防御,Akismet 不可用时自动降级为本地过滤,7×24 小时守护社区纯净。



✨ 核心特性

特性说明
零侵入通过 ThinkPHP 全局中间件拦截,不修改 community 核心代码
自动降级Akismet API 超时 / 5xx / 未配置时自动跳过,不阻断正常发帖
短路求值本地规则先跑(毫秒级),命中即拦截,不浪费 Akismet API 额度
智能豁免管理员会话、VIP 会员、注册 N 天老用户可分别豁免检测
拦截日志自动记录到数据库,后台可查看、批量清理
一键验证后台实时验证 Akismet API Key 有效性
自动读取首次安装时自动识别当前站点 URL,开箱即用
默认关键词内置 82 个常见垃圾关键词(代写、刷单、套现、博彩、色情等)


📦 安装

插件目录结构:

plugins/Akismet/
├── plugin.json
├── AkismetPlugin.php              # 主类(配置 / 自动建表 / 常量)
├── middleware.php                 # 全局中间件声明
├── routes.php                     # 后台路由
├── install.sql                    # 日志表 SQL(首次启用自动建表)
├── icon.svg
├── middleware/
│   └── AkismetGuard.php           # 核心拦截中间件
├── service/
│   ├── AkismetClient.php          # Akismet 云端 API 客户端
│   ├── LocalFilter.php            # 本地规则引擎
│   └── FilterLog.php              # 拦截日志(记录 / 查询 / 清理 / 统计)
├── controller/admin/
│   ├── Base.php
│   └── Index.php                  # 后台配置 + 日志管理
└── view/admin/
    ├── config.html                # 配置页
    └── logs.html                  # 拦截日志列表

步骤

  1. 将 Akismet/ 文件夹放到 plugins/ 目录下
  2. 清除 runtime 缓存让中间件编译生效:

  ```powershell

  Remove-Item -Recurse -Force runtime\cache\*  -ErrorAction SilentlyContinue

  Remove-Item -Recurse -Force runtime\temp\*   -ErrorAction SilentlyContinue

  ```

  1. 重启 Nginx(ThinkPHP 中间件注册在路由加载阶段,必须重启)
  2. 进入后台 → 插件管理 → 找到「垃圾评论拦截」→ 安装并启用
  3. 首次启用会自动创建 zsensakismetlog 日志表,无需手动执行 SQL


⚙️ 后台配置

后台路径:/admin/akismet

基本设置

配置项默认值说明
启用防垃圾检测✅ 开总开关
记录拦截日志✅ 开每次拦截写入数据库,便于事后审查
拦截模式直接拒绝reject = 禁止发布;hold = 允许但标记待审

Akismet 云端检测(可选但推荐)

在 https://akismet.com/ 注册免费账号,获取 API Key。

配置项默认值说明
启用 Akismet✅ 开关闭后仅使用本地规则引擎
API Key空在 akismet.com 注册后获得
站点 URL自动读取后台配置表的 site_domain → 当前请求 domain → config('app.url')
后台有一个「🔄 自动」按钮,点击即可一键填入检测到的当前站点地址。

本地规则引擎(始终生效)

配置项默认值说明
垃圾关键词82 个内置每行一个,忽略大小写子串匹配;可自由增删
最大链接数5内容中 URL 数量超限即垃圾;设 0 不限
最小有效字符数2去掉标点/空白/表情后的纯有效文本;设 0 不限
拒绝无意义内容✅ 开纯表情 / 纯标点 / 纯空白直接拦截

豁免白名单

配置项默认值说明
管理员免检测✅ 开超管后台会话跳过所有规则
VIP 会员免检测❌ 关需安装 vip 插件
注册 N 天后免检测0老用户信任白名单;设 0 不开启


🛡️ 拦截流程

社区 POST /topic/save  或  /reply/save
        ↓
  AkismetGuard 全局中间件
        ↓
  ① 仅拦截 POST + pathinfo 匹配 topic/save 或 reply/save
     (其他请求立即 next(),零开销)
        ↓
  ② 豁免检查 → 管理员 / VIP / 老用户 命中即放行
        ↓
  ③ 本地规则引擎(毫秒级)
     ├─ 垃圾关键词黑名单
     ├─ URL 链接数量超限
     ├─ 纯表情 / 纯标点(无意义)
     └─ 有效字符长度过短
        ↓ 未命中
  ④ Akismet 云端 API(5s 超时)
     POST https://rest.akismet.com/1.1/comment-check
     api_key / blog / user_ip / comment_content / comment_type
        ↓ 返回 true
  写入拦截日志 → 返回 JSON 错误 → 用户看到:
  "内容被安全系统判定为垃圾,请修改后重试:命中垃圾关键词代写论文"

短路设计

本地规则命中即拦截,不会再调用 Akismet API,既快又省额度。

降级设计

Akismet 状态行为
API Key 未填跳过云端,仅用本地规则
API Key 已填但超时跳过云端,本次请求放行(不阻断正常发帖)
HTTP 5xx / 403跳过云端,降级为本地规则
返回 invalid跳过云端(Key 失效,自动降级)
安全优先还是可用优先? 本插件选择「可用优先」——云端故障时不拦截,避免误伤正常用户。本地规则始终生效兜底。


📋 默认垃圾关键词(82 个)

代写论文、毕业论文代写、代发论文
免费领取、限时领取、点击领取
加QQ私聊、微信私聊、扫码联系
点击跳转链接、点击下方链接、复制打开浏览器、手机版直接搜、百度搜索一下
无需下载、一键生成、AI生成
免费试用、免费领取VIP、永久VIP
破解版、中文版破解、绿色版
软件下载、游戏下载
私服、外挂、作弊器、辅助工具
博彩、赌博、在线娱乐
亚洲男人天堂、色情、AV
交友聊天、约炮、一夜情、招嫖
办证、刻章、发票
高利贷、小额贷款
网络兼职、日赚、无风险、稳赚不赔
刷单、淘宝刷单、京东刷单、代刷单
代刷信誉、代刷好评、代刷收藏、代刷粉丝
代刷播放量、代点关注、代投票、代砍价
代抢火车票、代抢票
手机定位、通话录音、监听软件、手机窃听
信用卡套现、花呗套现、白条套现、网贷
APP下载链接、点击下载APP、打开APP
推广链接、佣金、返佣、高佣金、拉新、推广

后台关键词框支持自由增删,每行一个。想恢复默认 → 清空保存(系统会把空值合并回默认值)。



🔍 拦截日志

后台路径:/admin/akismet/logs

日志字段:

字段说明
时间拦截发生时间
来源发帖 / 回帖
用户用户昵称(游客显示为 "游客")
IP提交者 IP
拦截原因命中的关键词 / 链接数超限 / Akismet 判定等
Akismet云端判定 = Akismet 返回 true;本地规则 = 本地引擎拦截
内容预览被拦截内容前 500 字

清理操作:

  • 清空全部日志
  • 删除 30 天前的日志
  • 删除 7 天前的日志


🔧 开发者接口

手动检测

use plugins\Akismet\service\LocalFilter;
use plugins\Akismet\service\AkismetClient;
use plugins\Akismet\AkismetPlugin;

$cfg = AkismetPlugin::config();

// 仅本地规则
$reason = LocalFilter::check($text, $cfg);
if ($reason !== null) {
    // 命中垃圾
}

// 调 Akismet
$result = AkismetClient::check(
    apiKey: (string) $cfg['akismet_api_key'],
    blogUrl: (string) $cfg['akismet_blog_url'],
    content: $text,
    ip: '1.2.3.4',
    userAgent: $_SERVER['HTTP_USER_AGENT'] ?? '',
    commentType: 'comment',   // 或 'post'
);
// true = 垃圾  false = 非垃圾  null = 调用失败

// 验证 API Key
$ok = AkismetClient::verifyKey($apiKey, $blogUrl);

日志查询

use plugins\Akismet\service\FilterLog;

$result = FilterLog::recent($page = 1, $pageSize = 20);
// ['total' => N, 'page' => N, 'pages' => N, 'list' => [...]]

$summary = FilterLog::summary();
// ['total' => N, 'today' => N, 'topic' => N, 'reply' => N]

数据库表

CREATE TABLE zsens_akismet_log (
    id               INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    created_at       INT UNSIGNED NOT NULL DEFAULT 0,
    source           VARCHAR(20)  NOT NULL DEFAULT '',  -- 'topic' | 'reply'
    action           VARCHAR(20)  NOT NULL DEFAULT '',  -- 'reject'
    reason           VARCHAR(255) NOT NULL DEFAULT '',  -- 拦截原因
    user_id          INT          NOT NULL DEFAULT 0,
    username         VARCHAR(100) NOT NULL DEFAULT '',
    ip               VARCHAR(45)  NOT NULL DEFAULT '',
    content_preview  VARCHAR(500) NOT NULL DEFAULT '',
    akismet_result   VARCHAR(20)  NOT NULL DEFAULT '',  -- 'true' | ''
    KEY idx_created_at (created_at),
    KEY idx_user_id (user_id),
    KEY idx_source (source)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Akismet防垃圾拦截日志';

首次启用时由 AkismetPlugin::ensureSchema() 自动创建,表前缀跟随系统 config('database.connections.mysql.prefix')。



🏗️ 工作方式说明

为什么用全局中间件而不是 TopicPluginHooks?

  • TopicPluginHooks::afterSave 是帖子入库之后才触发,拦截时垃圾内容已经存进数据库 —— 无法达到防垃圾的目的
  • 全局中间件在请求进入控制器之前拦截,可以直接返回 JSON 错误给前端,帖子根本不会入库
  • 拦截目标通过 pathinfo 后缀匹配:

 ```

 /topic/save      → 拦截

 /reply/save      → 拦截

 其他所有路由     → 直接放行(零开销)

 ```

为什么 Akismet 故障时不拦截?

Akismet 官方 API 并非 100% 可靠(偶有超时 / 5xx)。如果把云端故障视为垃圾,会导致正常用户发帖大面积失败。所以本插件策略是:

本地规则永远生效,云端失败自动跳过 — 宁可少拦一两条垃圾,不能误伤一篇正常内容。

如果希望更严格,可在后台只启用「本地规则引擎」,关闭 Akismet 并加强关键词列表。



🐛 常见问题

Q: 安装后社区发帖 / 回帖报错「内容被安全系统判定为垃圾」

说明你当前提交内容命中了本地关键词或 Akismet 判定。可在后台查看拦截日志定位原因。

Q: Akismet 一直返回 API Key 无效?

  • 确认 Key 是在 akismet.com 注册后获取的
  • 站点 URL 必须与 Key 绑定的域名一致(或同属一个主域)
  • 后台填写的 URL 必须带 https:// 前缀,结尾不要带 /

Q: 拦截误杀了正常内容怎么办?

  • 从关键词黑名单里移除对应关键词
  • 临时在配置里关闭「启用防垃圾检测」紧急放行
  • 考虑把「豁免白名单」里的 VIP / 老用户打开

Q: 性能影响?

  • 中间件匹配:仅 pathinfo 字符串比较,纳秒级
  • 本地过滤:纯 PHP 正则 + 字符串操作,单条 < 1ms
  • Akismet API:约 200~500ms,5s 超时;只有前两层都放行才会调用


📜 License

由 kuakeba.cn 开发,保留所有权利。

更新记录 (2)

  • v1.0.01 2026-10-28
    修复检测逻辑
  • v1.0.0 2026-10-28
    正式发布
微信客服 微信客服 QQ官方交流群 QQ官方交流群