子比主题开发文档
使用指南Codestar Framework主题扩展在线部署AI 功能推荐插件赞助打赏

内容审核与发布安全

梳理子比主题 API 内容审核、百度审核接入、投稿评论私信审核、图片审核、论坛审核与人工审核边界。

模块边界

子比主题的内容审核不是一个独立发布系统,而是接在前台交互流程里的风险判断层。它会在用户上传图片、发布投稿、发表评论、发送私信、修改昵称签名、发布论坛帖子或创建论坛对象时调用审核接口;审核接口只负责判断内容风险,是否最终发布仍由主题的权限、人工审核、文章状态和论坛状态决定。

开发时要先记住这条边界:API 审核通过不等于用户拥有发布权限,也不等于可以绕过人工审核。主题里常见的直通条件是“API 审核通过 + 当前用户拥有免人工审核能力”,否则内容仍按主题原流程进入待审或阻断。

核心文件

文件作用
inc/class/api-audit-class.phpZibAudit 内容审核类,封装文本、图片、百度接口、token 缓存和审核结果转换
inc/options/admin-options.phpAPI 内容审核后台配置、各业务开关、百度 App Key 与 Secret Key
action/new_posts.php前台投稿发布前的文字审核和待审状态判断
action/comment.php评论提交前的文字审核和 pre_comment_approved 处理
action/user.php用户昵称、签名保存前的文字审核
inc/functions/zib-attachment.php图片上传进入 attachment 前的图片审核
inc/functions/message/functions/ajax.php私信发送前的文字审核
inc/functions/bbs/action/ajax-posts.php论坛帖子发布前的文字审核和待审状态判断
inc/functions/bbs/action/ajax-plate.php论坛版块图像与文本审核
inc/functions/bbs/action/ajax-term.php论坛话题、标签、分类图像与文本审核

后台配置

API 内容审核配置位于主题后台的系统工具分组内。核心选项如下:

配置项含义
api_audit_text_sdk文本审核接口,当前主题源码支持 baidu 或关闭
api_audit_img_sdk图像审核接口,当前主题源码支持 baidu 或关闭
audit_be_like_text文本“疑似”结果的处理策略
audit_be_like_img图片“疑似”结果的处理策略
audit_upload_img用户上传图片是否进入图片审核
audit_user_desc用户昵称和签名是否进入文本审核
audit_msg_private私信内容是否进入文本审核
audit_comment评论内容是否进入文本审核
audit_new_post前台投稿是否进入文本审核
audit_bbs_posts论坛发帖是否进入文本审核
audit_bbs_plate论坛版块标题和简介是否进入文本审核
audit_bbs_term论坛话题、标签、分类标题和简介是否进入文本审核
audit_sdk_baidu百度审核接口配置,包含 appkeysecretkey
audit_baidu_access_token本地缓存的百度 access_token 和过期时间

这些开关只决定是否调用审核接口,不替代原本的登录态、nonce、能力、长度、分类、上传大小和文件类型校验。

ZibAudit 类

常用入口:

方法用途
ZibAudit::ajax_text($content, $msg_prefix = '', $be_like = null)Ajax 流程中审核文本,明确不合规时直接输出 JSON 并 exit()
ZibAudit::ajax_image($file_id = 'file', $msg_prefix = '', $be_like = null)Ajax 流程中审核 $_FILES[$file_id] 图片,明确不合规时直接输出 JSON 并 exit()
ZibAudit::text($content, $sdk = '')只请求文本审核并返回结果,不直接中断 Ajax
ZibAudit::image($content, $sdk = '')只请求图片审核并返回结果,不直接中断 Ajax
ZibAudit::request($content, $type = 'text', $sdk = null)按文本或图片类型选择审核 SDK
ZibAudit::is_audit($return, $type = 'text')将审核返回值转换成是否可直通的布尔判断
ZibAudit::baidu($content, $type)调用百度文本或图片审核接口
ZibAudit::baidu_get_token()获取并缓存百度 access_token

ajax_text()ajax_image() 适合前台 Ajax 保存流程,因为它们能在不合规时立即返回统一错误。text()image() 适合后台测试、日志或需要自己决定后续状态的场景。

百度接口链路

百度配置来自:

$cofig = _pz('audit_sdk_baidu');

主题使用 appkeysecretkey 请求:

https://aip.baidubce.com/oauth/2.0/token

成功后缓存到:

update_option('audit_baidu_access_token', $res);

文本审核接口:

https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined

图片审核接口:

https://aip.baidubce.com/rest/2.0/solution/v1/img_censor/v2/user_defined

图片内容可以是 URL,也可以是本地上传文件。对本地文件,主题会读取文件内容并转成 base64:

ZibAudit::image_base64($content);

前台上传场景通常传的是 $_FILES[$file_id]['tmp_name'],不要把用户可控文件名或未校验 URL 当作可信审核对象。

审核结果

ZibAudit::_return() 会把接口返回整理成统一结构:

array(
    'conclusion'      => $conclusion,
    'conclusion_type' => $conclusionType,
    'msg'             => $msg,
    'data'            => $data,
)

百度常见结论类型:

conclusion_type含义处理建议
1合规可以继续进入主题后续权限和发布状态判断
2不合规阻断保存或进入人工处理,不要自动发布
3疑似按站点配置和当前版本源码处理,保守场景建议进入人工审核
4审核失败不应当自动发布,优先提示重试或进入人工审核

扩展开发时不要自己硬编码“接口返回成功就发布”。如果处于主题现有流程,优先使用 ZibAudit::ajax_text()ZibAudit::ajax_image()ZibAudit::is_audit(),并保留后续的用户能力判断。

前台投稿审核

前台投稿在 action/new_posts.php 中处理。主题先做标题、内容、分类、发布权限等校验,再进入内容合规判断:

$is_audit = false;
if (zib_current_user_can('new_post_audit_no')) {
    $is_audit = true;
} else {
    if (_pz('audit_new_post')) {
        $api_is_audit = ZibAudit::is_audit(ZibAudit::ajax_text($title . $content));
        if ($api_is_audit && zib_current_user_can('new_post_audit_no_manual')) {
            $is_audit = true;
        }
    }
}

关键点:

  • new_post_audit_no 表示用户拥有免审核权限,可以直接通过主题审核层。
  • audit_new_post 只决定是否调用 API 文本审核。
  • API 审核通过后,还要拥有 new_post_audit_no_manual,才会免人工审核。
  • 不满足直通条件时,文章仍应按主题原流程进入 pending 或对应待审状态。

新增投稿相关字段时,只在主题保存流程前后追加自己的校验和 Meta,不要单独创建一个绕过 zib_ajax_new_posts() 的发布入口。

评论审核

评论在 action/comment.php 中处理。主题会先检查评论内容长度,再判断当前用户是否免审、是否为快速回复、是否需要 API 审核:

if (zib_current_user_can('comment_audit_no', (!empty($_POST['comment_post_ID']) ? $_POST['comment_post_ID'] : 0))) {
    $is_audit = true;
} else {
    if (in_array(trim($_POST['comment']), zib_get_quick_often_items())) {
        $is_audit = true;
    }

    if (!$is_audit && _pz('audit_comment')) {
        $api_is_audit = ZibAudit::is_audit(ZibAudit::ajax_text(zib_comment_filters($_POST['comment'])));
        if ($api_is_audit && zib_current_user_can('comment_audit_no_manual')) {
            $is_audit = true;
        }
    }
}

审核直通后,主题通过 pre_comment_approved 将评论设为已审核:

add_filter('pre_comment_approved', function () {
    return 1;
});

扩展评论时要保留 comment_audit_nocomment_audit_no_manual、快速回复、评论频率和 WordPress 原生评论审核机制,不要只看 API 结果。

快捷回复与审核白名单

评论快捷回复有“系统”和“我的”两种来源,但审核白名单只读取系统快捷回复。zib_get_quick_often_items() 会按开关合并:

开关字段场景
bbs_comment_quick_sbbs_comment_quick_often论坛评论常用快捷回复
comment_quick_scomment_quick_often普通文章评论常用快捷回复

用户自己的快捷回复保存在 user meta quick_often,由 user_edit_quick_oftensave_user_quick_often 管理,只用于输入框里“我的”Tab 快速填充,不会被 zib_get_quick_often_items() 读取。因此扩展评论审核时,不要把个人快捷回复当成可信白名单。

如果确实要新增一组可免审核的系统短语,应保持“完全匹配后才免审核”的语义,并继续保留评论长度、人机验证、频率限制和 WordPress 原生审核机制。主题源码当前没有给 zib_get_quick_often_items() 预留过滤器;二开时不要直接把用户提交的 quick_often 写进系统配置。

用户资料与私信审核

用户资料保存会对昵称和签名进行审核:

if (_pz('audit_user_desc')) {
    ZibAudit::ajax_text($_POST['desc'] . $_POST['name'], __('昵称或签名', 'zib_language'));
}

私信发送会在黑名单判断之后、消息入库之前审核文本:

if (_pz('audit_msg_private')) {
    ZibAudit::ajax_text(Zib_Private::get_content($_POST['receive'], 'mini'));
}

这些入口适合阻断明显违规内容,不适合承担身份权限。保存用户资料仍要继续校验当前用户、字段长度、URL 格式和绑定关系;发送私信仍要继续校验发送者、接收者、黑名单、消息频率和会话状态。

图片上传审核

图片审核集中接在 zib_php_upload() 里:

if ('auto' == $ajax_audit) {
    $ajax_audit = _pz('audit_upload_img', false);
}

if ($ajax_audit && stristr($_FILES[$file]['type'], 'image')) {
    ZibAudit::ajax_image($file, $msg_prefix);
}

多图上传时,主题还会逐个检查 file_1file_2 等后续文件。审核通过后才进入:

media_handle_upload($file, $post_id, [], $overrides);

所以自定义上传入口应优先复用 zib_php_upload()。如果必须自己处理上传,也要在写入 attachment 前调用 ZibAudit::ajax_image(),并继续保留 MIME、大小、登录态、nonce、媒体库隔离和附件归属逻辑。更多上传边界见 媒体上传

论坛审核

论坛帖子发布在 inc/functions/bbs/action/ajax-posts.php 中判断:

if (zib_bbs_current_user_can('posts_save_audit_no') || ($post_id && zib_bbs_current_user_can('posts_audit', $post_id)) || ($plate && zib_bbs_current_user_can('posts_audit', $plate))) {
    $is_audit = true;
} else {
    if (_pz('audit_bbs_posts')) {
        $api_is_audit = ZibAudit::is_audit(ZibAudit::ajax_text($post_title . $post_content));
        if ($api_is_audit && zib_bbs_current_user_can('posts_save_audit_no_manual')) {
            $is_audit = true;
        }
    }
}

论坛对象还有两类审核入口:

场景审核点
创建或编辑版块audit_upload_img 审核版块图像,audit_bbs_plate 审核标题和简介
创建或编辑话题、标签、分类audit_upload_img 审核图像,audit_bbs_term 审核标题和简介

论坛扩展要同时考虑版块权限、版主权限、帖子审核权限、用户发帖能力和对象状态。API 审核只是在保存前增加一道风险检查,不能替代 zib_bbs_current_user_can()

新增 Ajax 审核示例

下面示例用于新增一个前台内容保存入口。它保留登录态、nonce、字段清洗、API 审核和统一 JSON 响应:

function zib_docs_save_profile_note()
{
    if (!is_user_logged_in()) {
        zib_send_json_error(__('请先登录', 'zib_language'));
    }

    zib_ajax_verify_nonce();

    $user_id = get_current_user_id();
    $note    = !empty($_POST['note']) ? wp_kses_post(wp_unslash($_POST['note'])) : '';

    if (zib_new_strlen($note) < 2) {
        zib_send_json_error(__('内容过短', 'zib_language'));
    }

    if (_pz('api_audit_text_sdk')) {
        ZibAudit::ajax_text($note, __('补充资料', 'zib_language'));
    }

    zib_update_user_meta($user_id, 'profile_note', $note);

    zib_send_json_success(array(
        'msg'  => __('保存成功', 'zib_language'),
        'note' => $note,
    ));
}
add_action('wp_ajax_docs_save_profile_note', 'zib_docs_save_profile_note');

如果业务不是“失败即阻断”,而是“失败进入待审”,可以只拿审核结果,再决定状态:

function zib_docs_insert_pending_item($title, $content)
{
    $is_audit = false;

    if (_pz('audit_new_post')) {
        $audit_result = ZibAudit::ajax_text($title . $content, __('内容', 'zib_language'));
        $is_audit     = ZibAudit::is_audit($audit_result);
    }

    $status = $is_audit && zib_current_user_can('new_post_audit_no_manual') ? 'publish' : 'pending';

    return wp_insert_post(array(
        'post_type'    => 'post',
        'post_title'   => wp_strip_all_tags($title),
        'post_content' => wp_kses_post($content),
        'post_status'  => $status,
    ), true);
}

注意这里仍然检查 new_post_audit_no_manual。不要因为 API 审核返回合规就直接给所有用户发布权限。

图片审核示例

新增图片上传入口时,继续复用主题上传封装:

function zib_docs_upload_checked_image()
{
    if (!is_user_logged_in()) {
        zib_send_json_error(__('请先登录', 'zib_language'));
    }

    zib_ajax_verify_nonce('user_upload');

    if (empty($_FILES['file']) || !stristr($_FILES['file']['type'], 'image')) {
        zib_send_json_error(__('请选择图片文件', 'zib_language'));
    }

    $attach_id = zib_php_upload('file', 0, 'auto', __('图片', 'zib_language'));
    if (!empty($attach_id['error'])) {
        zib_send_json_error($attach_id['msg']);
    }

    zib_send_json_success(zib_prepare_attachment_for_js($attach_id));
}
add_action('wp_ajax_docs_upload_checked_image', 'zib_docs_upload_checked_image');

'auto' 会读取 audit_upload_img,保持和主题后台配置一致。业务需要强制审核时可以传 true,但不要绕过 zib_php_upload() 里的媒体处理。

人工审核与通知

内容审核通常和人工审核、通知、日志一起使用:

场景可用节点
投稿进入待审new_posts_pending
投稿新增成功new_add_posts
投稿编辑成功new_edit_posts
评论进入待审WordPress 评论状态和后台评论审核
论坛帖子审核posts_audit、版主权限和论坛审核弹窗
论坛版块审核plate_audit、版块管理权限

如果要记录审核日志,可以挂保存后的 Action,并只保存必要结论,不要把第三方接口原始响应、命中词、密钥、服务器路径或用户隐私写进前端可见位置。

常见风险

风险说明
把 API 审核当权限系统审核接口只判断内容风险,不判断用户能否发布、编辑或上传
API 合规后直接发布主题原逻辑还需要免人工审核能力,否则应进入待审
绕过 zib_php_upload()会丢失图片审核、MIME、大小、attachment 和媒体库隔离
只审核标题不审核正文投稿、帖子、版块、话题通常要拼接标题和正文一起审核
不处理审核失败第三方接口超时或失败时不应默认发布
暴露接口原文审核命中词、access token、错误响应不应直接给普通用户或前端页面
缓存动态接口投稿、评论、私信、上传 Ajax 不能被 CDN 或页面缓存缓存
忽略管理员绕过ZibAudit 对管理员操作有特殊处理,测试时要用普通用户验证

调试入口

现象优先检查
审核完全不触发对应业务开关、api_audit_text_sdkapi_audit_img_sdk、当前用户是否管理员
百度提示配置缺失audit_sdk_baidu.appkeyaudit_sdk_baidu.secretkey
百度 token 获取失败服务器网络、接口返回、audit_baidu_access_token 缓存
投稿仍进入待审是否拥有 new_post_audit_no_manual,是否满足主题发布能力
评论仍待审comment_audit_no_manual、WordPress 评论设置、评论频率限制
图片上传变慢audit_upload_img、第三方接口耗时、服务器到接口网络
前端没有错误提示ajax_text() / ajax_image() 只有明确不合规时才会输出阻断错误

参考源码

本页根据 inc/class/api-audit-class.phpinc/options/admin-options.phpaction/new_posts.phpaction/comment.phpaction/user.phpinc/functions/zib-attachment.phpinc/functions/message/functions/ajax.phpinc/functions/bbs/action/ajax-posts.phpinc/functions/bbs/action/ajax-plate.phpinc/functions/bbs/action/ajax-term.php 蒸馏整理。

On this page