跳到内容

内容安全 ​

受众:开发者 摘要:Content Safety starter 使用方式、Provider 抽象、keyword / noop / 云端 provider 和自建 AI 模型内容安全接入边界。

Content Safety starter 提供统一的敏感内容检测入口,用于 Blog、Forum、Chat、Mall 评价、用户资料、广告素材等场景。

Content Safety starter 保持轻量:内置 keyword、noop、openai、google、aliyun、tencent、volcengine、baidu、ai-model 和 self-hosted provider,不引入重量级第三方内容安全 SDK。配置和代码边界按短信、存储等模块的 Provider 模式设计,后续新增内容安全服务商时继续通过 Provider 扩展。

后台敏感词库、检测日志、人工复核任务、批量扫描、文件扫描和 CSV 导出由 spring-open-core-content-safety 承接;后台 API 统一挂载在 /api/v1/content-safety/**,权限字符串使用 content-safety:*,配置前缀使用 spring.open.content-safety.*。

何时使用 ​

适合:

  • 发布前检测文本、昵称、签名、评论、聊天消息和视频内容元数据。
  • 按场景决定通过、拒绝或进入人工审核。
  • 给内容审核、违规日志、通知事件和广告素材审核提供统一底座。
  • 给 Video 等业务模块提供统一 action / riskLevel / reason 摘要,由业务模块自行决定公开过滤、待复核展示和播放地址隐藏。
  • 后续替换或组合多个内容安全服务商。

不适合:

  • 全局粗暴拦截所有请求体。
  • 替代富文本 XSS 清洗。
  • 在业务模块里直接调用第三方内容安全 SDK。
  • 把聊天实时消息强制绑定慢速同步检测。

快速开始 ​

按需引入:

xml
<dependency>
    <groupId>com.springopen</groupId>
    <artifactId>spring-open-starter-content-safety</artifactId>
</dependency>

默认启用,未配置敏感词时 keyword provider 会直接通过:

yaml
spring:
  open:
    content-safety:
      default-provider: keyword
      providers:
        keyword:
          provider: keyword
          keywords:
            - spam
            - blocked

keyword provider 的词有两个来源,可同时生效:

  • 配置词:上面的 keywords / regexes 列表,按 provider 级 action-on-match / risk-level-on-match 统一决策。
  • 词源 SPI(ContentSafetyKeywordSource):业务侧注册的扩展词源,每条词自带 matchType(keyword / regex)、riskLevel 和 action,按词级语义决策。装配 spring-open-core-content-safety 后,后台敏感词管理(content_safety_word 表)会通过内置的数据库词源自动接入:管理员在后台增删改敏感词后最长 30 秒内对所有内容检测生效;action=reject 直接拒绝,action=review 转待复核。词源读库失败时沿用上一份词快照,不阻断内容发布。

配置词与词源词同时命中时整体动作取最严(reject 优先于 review),风险等级取命中项中的最高级。

Facade 使用:

java
ContentSafetyResult result = ContentSafety.check(ContentSafetyRequest.builder()
        .scene("forum.topic")
        .bizType("forum-topic")
        .content("hello")
        .build());

if (result.isRejected()) {
    // 拒绝发布
}

if (result.isReviewRequired()) {
    // 进入人工审核
}

Provider ​

配置结构:

yaml
spring:
  open:
    content-safety:
      enabled: true
      default-provider: keyword
      fallback-providers:
        - noop
      providers:
        keyword:
          provider: keyword
          enabled: true
          word-set: default
          keywords:
            - blocked
          action-on-match: review
        noop:
          provider: noop
          enabled: true
        openai-main:
          provider: openai
          enabled: false
          api-key: ${OPENAI_API_KEY:}
          model: omni-moderation-latest
        google-main:
          provider: google
          enabled: false
          access-token: ${GOOGLE_CLOUD_LANGUAGE_ACCESS_TOKEN:}
        aliyun-main:
          provider: aliyun
          enabled: false
          endpoint: https://green-cip.cn-shanghai.aliyuncs.com
          service: comment_detection_pro
          access-key-id: ${ALIYUN_CONTENT_SAFETY_ACCESS_KEY_ID:}
          access-key-secret: ${ALIYUN_CONTENT_SAFETY_ACCESS_KEY_SECRET:}
        tencent-main:
          provider: tencent
          enabled: false
          region: ap-guangzhou
          biz-type: TencentCloudDefault
          secret-id: ${TENCENT_CONTENT_SAFETY_SECRET_ID:}
          secret-key: ${TENCENT_CONTENT_SAFETY_SECRET_KEY:}
        volcengine-main:
          provider: volcengine
          enabled: false
          region: cn-north-1
          service: content_security
          access-key-id: ${VOLCENGINE_CONTENT_SAFETY_ACCESS_KEY_ID:}
          access-key-secret: ${VOLCENGINE_CONTENT_SAFETY_ACCESS_KEY_SECRET:}
          properties:
            app-id: ${VOLCENGINE_CONTENT_SAFETY_APP_ID:}
        baidu-main:
          provider: baidu
          enabled: false
          access-token: ${BAIDU_CONTENT_SAFETY_ACCESS_TOKEN:}
        local-model:
          provider: ai-model
          enabled: false
          endpoint: ${LOCAL_CONTENT_SAFETY_ENDPOINT:}
          api-key: ${LOCAL_CONTENT_SAFETY_API_KEY:}
          model: moderation-v1
        private-model:
          provider: self-hosted
          enabled: false
          endpoint: ${PRIVATE_CONTENT_SAFETY_ENDPOINT:}
          api-key: ${PRIVATE_CONTENT_SAFETY_API_KEY:}
          model: moderation-v1

说明:

  • providers 的 map key 是可命名 provider 实例,例如 keyword、keyword-strict、tencent-main。
  • providers.*.provider 是真实 provider 实现类型,例如 keyword、noop、tencent、aliyun、volcengine、baidu、ai-model、self-hosted。
  • 同一个 provider 实现类型可以配置多个 provider 实例。
  • 业务模块只调用 ContentSafety / ContentSafetyManager,不直接依赖第三方 SDK。

配置 ​

配置默认值说明
spring.open.content-safety.enabledtrue是否启用内容安全 starter
spring.open.content-safety.default-providerkeyword默认 provider
spring.open.content-safety.fallback-providersnoopprovider 不可用时的后备 provider
spring.open.content-safety.providers.*.provider-provider 实例使用的实现类型
spring.open.content-safety.providers.*.enabledtrueprovider 是否启用
spring.open.content-safety.providers.*.endpoint按 provider服务地址;OpenAI 默认 https://api.openai.com/v1/moderations,Google 默认 https://language.googleapis.com/v1/documents:moderateText,阿里云默认 https://green-cip.cn-shanghai.aliyuncs.com,腾讯云默认 https://tms.tencentcloudapi.com,火山默认 https://riskcontrol.volcengineapi.com,百度默认 https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined,自建模型必须显式配置
spring.open.content-safety.providers.*.timeout10sHTTP 请求超时时间
spring.open.content-safety.providers.*.api-key空OpenAI / 自建模型等 Bearer Token
spring.open.content-safety.providers.*.access-token空Google Cloud Natural Language OAuth Access Token 或百度内容审核 access token
spring.open.content-safety.providers.*.model按 providerOpenAI moderation 模型或自建模型名;OpenAI 默认 omni-moderation-latest
spring.open.content-safety.providers.*.service按 provider阿里云 TextModerationPlus 服务或火山业务风险服务;阿里云默认 comment_detection_pro,火山默认 content_security
spring.open.content-safety.providers.*.access-key-id空阿里云 / 火山 AccessKey ID
spring.open.content-safety.providers.*.access-key-secret空阿里云 / 火山 AccessKey Secret
spring.open.content-safety.providers.*.secret-id空腾讯云 SecretId
spring.open.content-safety.providers.*.secret-key空腾讯云 SecretKey
spring.open.content-safety.providers.*.region按 provider腾讯云 / 火山地域;腾讯云默认 ap-guangzhou,火山默认 cn-north-1
spring.open.content-safety.providers.*.biz-type按 provider腾讯云策略 BizType,默认 TencentCloudDefault
spring.open.content-safety.providers.*.properties.app-id空火山内容安全应用 ID
spring.open.content-safety.providers.*.properties.actionTextSliceRisk火山 OpenAPI Action
spring.open.content-safety.providers.*.properties.version按 provider火山 API Version 或云厂商扩展版本
spring.open.content-safety.providers.*.properties.signing-servicebusinessSecurity火山 OpenAPI 签名服务名
spring.open.content-safety.providers.*.keywords空keyword provider 使用的关键词
spring.open.content-safety.providers.*.regexes空keyword provider 使用的正则规则
spring.open.content-safety.providers.*.ignore-casetruekeyword / regex 是否忽略大小写
spring.open.content-safety.providers.*.action-on-matchreview命中后的建议动作:allow / review / reject
spring.open.content-safety.providers.*.risk-level-on-matchmedium命中后的风险等级

OpenAI Provider ​

openai provider 对接 OpenAI Moderations API,适合作为国际化内容审核默认服务:

yaml
spring:
  open:
    content-safety:
      default-provider: openai-main
      providers:
        openai-main:
          provider: openai
          enabled: true
          api-key: ${OPENAI_API_KEY:}
          model: omni-moderation-latest

说明:

  • 默认调用 https://api.openai.com/v1/moderations。
  • 官方默认模型为 omni-moderation-latest。
  • 命中后默认返回 review,如需直接拒绝可配置 action-on-match: reject。
  • OpenAI 返回的分类会转换为 ContentSafetyMatch,前端和业务模块不需要感知 OpenAI 原始响应结构。

参考:

Google Provider ​

google provider 对接 Google Cloud Natural Language documents:moderateText REST API,适合作为海外内容审核服务的可选方案:

yaml
spring:
  open:
    content-safety:
      default-provider: google-main
      providers:
        google-main:
          provider: google
          enabled: true
          access-token: ${GOOGLE_CLOUD_LANGUAGE_ACCESS_TOKEN:}

说明:

  • 默认调用 https://language.googleapis.com/v1/documents:moderateText。
  • Google 官方接口要求 OAuth 授权,本框架不内置服务账号换 token 逻辑,避免引入较重 Google Auth SDK;部署时把外部获取到的短期 access token 注入配置即可。
  • moderationCategories 会按置信度转换为统一 ContentSafetyMatch;默认阈值为 0.4,可通过 properties.threshold 调整。

参考:

Aliyun Provider ​

aliyun provider 对接阿里云内容安全 TextModerationPlus,适合作为国内内容审核服务的可选方案:

yaml
spring:
  open:
    content-safety:
      default-provider: aliyun-main
      providers:
        aliyun-main:
          provider: aliyun
          enabled: true
          endpoint: https://green-cip.cn-shanghai.aliyuncs.com
          service: comment_detection_pro
          access-key-id: ${ALIYUN_CONTENT_SAFETY_ACCESS_KEY_ID:}
          access-key-secret: ${ALIYUN_CONTENT_SAFETY_ACCESS_KEY_SECRET:}

说明:

  • 默认调用 https://green-cip.cn-shanghai.aliyuncs.com。
  • 请求使用阿里云 OpenAPI HMAC-SHA1 签名,不引入 green20220302 SDK。
  • service 可按场景切换,例如 chat_detection_pro、comment_detection_pro、nickname_detection_pro、ugc_moderation_byllm 等。
  • Data.RiskLevel=low 转为 allow,medium 转为 review,high 转为 reject。

参考:

Tencent Provider ​

tencent provider 对接腾讯云 TMS TextModeration,适合作为国内内容审核服务:

yaml
spring:
  open:
    content-safety:
      default-provider: tencent-main
      providers:
        tencent-main:
          provider: tencent
          enabled: true
          region: ap-guangzhou
          biz-type: TencentCloudDefault
          secret-id: ${TENCENT_CONTENT_SAFETY_SECRET_ID:}
          secret-key: ${TENCENT_CONTENT_SAFETY_SECRET_KEY:}

说明:

  • 默认调用 https://tms.tencentcloudapi.com。
  • 请求使用腾讯云 TC3-HMAC-SHA256 签名。
  • Suggestion=Pass 转为 allow,Suggestion=Review 转为 review,Suggestion=Block 转为 reject。
  • 腾讯云返回的 Label、Keywords、Score 会转换为统一 ContentSafetyResult。

参考:

Volcengine Provider ​

volcengine provider 对接火山引擎业务风险识别文本风险接口,适合作为国内内容审核服务的可选方案:

yaml
spring:
  open:
    content-safety:
      default-provider: volcengine-main
      providers:
        volcengine-main:
          provider: volcengine
          enabled: true
          endpoint: https://riskcontrol.volcengineapi.com
          region: cn-north-1
          service: content_security
          access-key-id: ${VOLCENGINE_CONTENT_SAFETY_ACCESS_KEY_ID:}
          access-key-secret: ${VOLCENGINE_CONTENT_SAFETY_ACCESS_KEY_SECRET:}
          properties:
            app-id: ${VOLCENGINE_CONTENT_SAFETY_APP_ID:}

说明:

  • 默认请求 Action=TextSliceRisk、Version=2022-11-07,通过 properties.app-id 传递火山应用 ID。
  • 请求使用火山 OpenAPI HMAC-SHA256 签名,不引入火山 SDK。
  • Decision=Pass 转为 allow,Block / Reject 转为 reject,其他风险决策默认转为 review。
  • Data.Results、FinalLabel、DecisionLabel、Score 会转换为统一 ContentSafetyResult。

参考:

Baidu Provider ​

baidu provider 对接百度智能云内容审核平台文本接口:

yaml
spring:
  open:
    content-safety:
      default-provider: baidu-main
      providers:
        baidu-main:
          provider: baidu
          enabled: true
          access-token: ${BAIDU_CONTENT_SAFETY_ACCESS_TOKEN:}

说明:

  • 默认调用 https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined。
  • 百度接口使用 access_token 鉴权;本框架不内置 token 换取和刷新逻辑,部署时由外部任务把有效 token 注入配置。
  • conclusionType=1 转为 allow,2 转为 reject,3 转为 review,4 视为 provider 调用失败。
  • data[].hits[].words 会脱敏后转换为统一 ContentSafetyMatch。

参考:

AI Model Provider ​

ai-model / self-hosted provider 面向自建或内网模型服务,使用轻量 HTTP JSON contract,避免 starter 直接绑定具体模型 SDK。两者使用同一请求 / 响应协议;self-hosted 更适合作为私有模型网关的业务可见 provider 名:

yaml
spring:
  open:
    content-safety:
      default-provider: local-model
      providers:
        local-model:
          provider: ai-model
          enabled: true
          endpoint: https://model.example.internal/moderations
          api-key: ${LOCAL_CONTENT_SAFETY_API_KEY:}
          model: moderation-v1

请求体会发送 model、input、contentType、scene、bizType 和请求扩展属性。响应支持以下轻量字段:

json
{
  "action": "review",
  "riskLevel": "medium",
  "reason": "custom-model.flagged",
  "matches": [
    {"type": "label", "category": "spam", "keyword": "coupon", "score": 0.72}
  ]
}

说明:

  • allowed=true 或 action=allow|pass 且无高风险时转为 allow。
  • action=reject|block|deny 或 riskLevel=high 转为 reject。
  • 其他命中默认转为 review。

Provider 选择顺序 ​

未显式指定 provider 时,Manager 按顺序选择:

  1. ContentSafetyRouteResolver 返回的候选 provider。
  2. default-provider。
  3. fallback-providers。

显式指定 provider 时,只使用该 provider。

源码机制骨架 ​

类型机制职责
ContentSafety静态 Facade,给业务模块提供最短检测入口
ContentSafetyManagerProvider将 Facade 绑定到 Spring 容器内的 ContentSafetyManager
ContentSafetyManager检测编排入口,负责请求校验、provider 路由、fallback、事件通知和异常语义
DefaultContentSafetyManager默认 Manager 实现,按显式 provider、路由解析器、默认 provider、fallback provider 的顺序生成候选列表
ContentSafetyRouteResolver场景化 provider 路由扩展点,可按 scene、bizType、用户、语言或租户返回候选 provider
ContentSafetyProviderProvider SPI,只负责调用具体检测策略或外部服务并返回统一结果
ContentSafetyProviderContext已解析的 provider 实例上下文,区分配置实例名和实现类型
ContentSafetyCheckListener检测事件监听器,用于审计、统计或复核任务生成;监听器失败不影响检测结果
ContentSafetyCheckEvent检测事件,记录候选 provider、最终 provider、结果、异常和耗时
ContentSafetyRequest检测请求,只描述业务场景、对象标识、内容类型和待检测文本
ContentSafetyResult统一结果,返回 allow / review / reject 建议、风险等级、命中摘要和轻量 metadata

Provider 实例名和实现类型是两个概念:tencent-main、tencent-strict 可以都是 provider: tencent。Manager 先按实例名读取配置,再用实现类型找到对应 ContentSafetyProvider。

检测成功或最终失败后都会触发 ContentSafetyCheckListener;监听器异常会被吞掉,不能反向阻塞用户发布、评论或聊天发送。

复杂场景建议写 ContentSafetyRouteResolver,不要在 YAML 里堆路由 DSL:

java
@Bean
ContentSafetyRouteResolver contentSafetyRouteResolver() {
    return request -> {
        if ("chat.message".equals(request.getScene())) {
            return List.of("keyword-chat");
        }
        return List.of();
    };
}

检测事件监听 ​

每次内容安全检测最终成功或失败后,Manager 会发布 ContentSafetyCheckEvent 给所有 ContentSafetyCheckListener。

这个扩展点用于后续落库检测日志、运营审计、失败统计和审核任务生成。Listener 失败不会影响本次内容安全判断,避免日志系统异常反向阻塞用户发布、评论或聊天链路。

java
@Bean
ContentSafetyCheckListener contentSafetyCheckListener() {
    return event -> {
        // event.request():业务场景、bizType、bizId、用户和内容类型
        // event.providerCandidates():本次候选 provider
        // event.result():最终检测结果
        // event.exception():最终失败异常
        // event.elapsed():检测耗时
    };
}

业务模块仍然只关心 ContentSafetyResult 的建议动作;检测日志、审核任务和运维报表由 spring-open-core-content-safety 通过 Listener 承接,业务模块只按需贡献批量检测来源或消费检测结果。

已接入模块 ​

当前已有这些业务模块消费内容安全底座:

模块场景rejectreview
Blog文章发布 / 编辑、评论提交拒绝保存并返回业务错误文章转为草稿,评论转为隐藏
Forum主题发布 / 编辑、回复提交拒绝保存并返回业务错误主题 / 回复转为隐藏
Conversation聊天消息发送、附件名称检测拒绝发送,不落库、不推送阻断发送,提示内容需调整
CMS后台批量检测 cms-content 来源不直接修改业务内容检测日志进入内容安全复核队列
Mall后台批量检测 mall-review 来源不直接修改商品评价检测日志进入内容安全复核队列

检测日志由 spring-open-core-content-safety 监听器统一落库,仅记录业务场景、Provider、动作、风险等级、耗时、长度等元数据,不保存被检测标题或正文原文。

聊天消息是实时体验,第一阶段不引入“已发送但待审核”的中间态。消息文本和附件名称会在消息落库、附件绑定、未读更新和 WebSocket 推送前统一检测;命中 reject 或 review 都直接阻断发送。

后台批量检测调度只负责重新触发检测和生成检测日志,不直接改 CMS 内容、Blog 文章 / 评论或 Mall 评价状态。当前支持这些 sourceType:

  • cms-content:CMS 内容标题、摘要、正文和 SEO 摘要。
  • blog-article:Blog 文章标题、摘要、付费试看和正文。
  • blog-comment:Blog 评论昵称和正文。
  • mall-review:商城评价商品名称、评价正文和商家回复。

内容安全运维日志 ​

spring-open-core-content-safety 已内置检测日志落库监听器。每次内容安全检测成功或失败后,会记录检测元数据到 content_safety_check_log:

  • 记录 scene / bizType / bizId / contentType / userId。
  • 记录 provider 候选、最终 provider、动作、风险等级、命中数量、耗时和异常摘要。
  • 不记录被检测的标题或正文原文,只记录标题长度和正文长度,避免敏感内容二次沉淀。

后台运维接口:

方法路径说明
POST/api/v1/admin/content-safety/batch-scans按业务来源批量触发内容安全检测
GET/api/v1/content-safety/words分页查询敏感词库
GET/api/v1/content-safety/words/{id}查询敏感词详情
POST/api/v1/content-safety/words新增敏感词
PUT/api/v1/content-safety/words/{id}更新敏感词
POST/api/v1/content-safety/words/{id}/enable启用敏感词
POST/api/v1/content-safety/words/{id}/disable停用敏感词
DELETE/api/v1/content-safety/words/{id}删除敏感词
DELETE/api/v1/content-safety/words批量删除敏感词
GET/api/v1/content-safety/check-logs分页查询检测日志
GET/api/v1/content-safety/check-logs/{id}查询检测日志详情
GET/api/v1/content-safety/review-tasks分页查询需要人工复核的检测任务
GET/api/v1/content-safety/review-tasks/{id}查询需要人工复核的检测任务详情
POST/api/v1/content-safety/review-tasks/{id}/approve将复核任务标记为已通过
POST/api/v1/content-safety/review-tasks/{id}/reject将复核任务标记为已拒绝
POST/api/v1/content-safety/review-tasks/{id}/close将复核任务标记为已关闭
POST/api/v1/content-safety/review-tasks/batch/approve批量将复核任务标记为已通过
POST/api/v1/content-safety/review-tasks/batch/reject批量将复核任务标记为已拒绝
POST/api/v1/content-safety/review-tasks/batch/close批量将复核任务标记为已关闭
POST/api/v1/content-safety/review-tasks/auto-handle-expired按配置批量处理超时仍未人工复核的任务

权限:

  • content-safety:check-log:view
  • content-safety:word:view
  • content-safety:word:create
  • content-safety:word:update
  • content-safety:word:delete
  • content-safety:review-task:view
  • content-safety:review-task:update

敏感词库写入 content_safety_word,同一 wordSet + word 保持唯一;每条规则可维护分类、风险等级、匹配类型、命中动作、启停状态和说明。wordSet 默认 default,category 默认 general,风险等级默认 medium,匹配类型默认 keyword,命中动作默认 review。

审核任务入口复用检测日志中 reviewRequired=true 的记录,不额外保存被检测原文。单条和批量复核动作都会通过审批工作流 content-safety.review 校验来源状态、动作、权限快照和备注要求,再只记录 reviewStatus / reviewAction / reviewRemark / reviewedBy / reviewedAt 审计字段,不直接修改 Blog、Forum、Chat、Mall 等业务对象状态;业务侧具体放行、拒绝或超时处理继续由各模块自己的审核状态机或事件联动承接。

reject 要求填写备注,approve / close 可不填备注。人工动作要求调用方具备 content-safety:review-task:update 权限;超时自动处理使用 auto-approve / auto-reject / auto-close 动作,不携带人工操作人。

超时自动处理默认启用,默认动作是 approve,符合“审核未及时处理时默认放行”的开发体验。若业务场景更敏感,可以改为 reject 或 close:

yaml
spring:
  open:
    content-safety:
        review:
          auto:
            enabled: true
            auto-startup: false
            timeout: 24h
            fixed-delay: 10m
            action: approve
            limit: 100
            remark: 内容安全复核超时自动通过

检测日志落库且需要人工复核时,系统会按 timeout 向专用 content-safety 队列投递 content-safety.review.auto-handle 延迟 Queue 消息;消费时会重新读取复核状态,已经人工处理或不再满足复核条件的记录会安全跳过。auto-startup 和 fixed-delay 仅作为旧固定间隔调度配置保留,默认不再注册周期扫描。后台也可以手动调用 POST /api/v1/content-safety/review-tasks/auto-handle-expired 立即处理一批超时任务。

自动处理只更新内容安全复核审计字段:

  • reviewStatus:按 action 写入 approved / rejected / closed。
  • reviewAction:写入 auto-approve / auto-reject / auto-close。
  • reviewRemark:写入配置的自动处理备注。
  • reviewedBy:为空,表示系统自动处理。
  • reviewedAt:自动处理时间。

Admin 后台已接入两个运维页面:

页面路由能力
内容安全词库/#/content-safety/words分页、筛选、详情、新增 / 编辑、启用 / 停用、删除 / 批量删除敏感词,并展示词库、分类、风险等级、匹配类型和命中动作
内容安全检测日志/#/content-safety/check-logs分页、筛选、详情、结果状态展示、业务快捷筛选、图片文件批量检测、按当前筛选创建 CSV 导出异步任务,并可把需要复核的记录带入同一业务筛选条件跳转到复核任务页
内容安全复核任务/#/content-safety/review-tasks分页、筛选、接收检测日志页 URL 筛选、业务快捷筛选、详情、通过 / 拒绝 / 关闭复核、批量通过 / 拒绝 / 关闭复核、按当前筛选创建 CSV 导出异步任务、手动触发超时自动处理和检测日志跳转

业务快捷筛选只暴露已经真实接入内容安全 contract 的来源。后端已提供 /api/v1/admin/content-safety/batch-scans 统一触发 CMS 内容、Blog 文章、Blog 评论和 Mall 评价批量检测;Admin 视图后续可按该 contract 接入来源选择和触发按钮,不伪造本地预览数据。

Keyword Provider ​

keyword provider 支持:

  • 普通关键词匹配。
  • 正则匹配。
  • 大小写忽略。
  • 命中后返回 review 或 reject。
  • 命中词脱敏返回,避免检测结果泄露完整敏感词。

未配置关键词和正则时,keyword provider 直接通过。

Noop Provider ​

noop provider 始终通过,适合:

  • 开发环境。
  • 未启用真实内容安全时的 fallback。
  • 单进程隔离诊断或兼容模式。

生产环境不建议只依赖 noop。

后续接入 ​

后续第三方 provider 按同一边界扩展:

  • volcengine:火山引擎内容安全。
  • baidu:百度智能云内容审核。
  • ai-model:AI Model 底座成熟后的模型审核。
  • self-hosted:私有化部署或内网自建模型审核服务。

第三方 SDK 只出现在对应 provider 实现内部,不向 Controller、Service、DTO 或业务模块泄露。

与审核关系 ​

内容安全只给出建议动作:

  • allow:可通过。
  • review:进入人工审核。
  • reject:拒绝。

Blog / Forum 第一阶段会先把 review 内容转为草稿或隐藏;Conversation 会在发送前阻断。人工审核任务、审核超时默认动作、审核日志和通知事件由 spring-open-core-content-safety 承接,业务侧具体状态流转继续由各业务模块处理。

验证 ​

bash
./mvnw -pl spring-open-starters/spring-open-starter-content-safety -am test -DskipITs
git diff --check

Released under the Apache License 2.0.